zoukankan      html  css  js  c++  java
  • urllib3

    urllib中的API大都与URL相关,所有可以得出这样一个结论,urllib主要侧重于URL的请求构造。而urllib2侧重于HTTP请求的处理,urllib3则是服务于升级的HTTP1.1标准,且拥有高效的HTTP连接池管理及HTTP代理服务的功能库。
    urllib3的主要特性是
    1.线程安全
    2.连接池
    3.客户端SSL/TLS验证
    4.使用multipart编码上传文件
    5.协助处理重复请求和HTTP重定位
    6.支持压缩编码
    7.支持HTTP和SCOKS代理
    8.100%测试覆盖率






    以下内容主要讲解
    1.发送请求
    2.设置HTTP请求头
    3.获取HTTP响应头
    4.上传文件
    5.超时异常捕获











    一.发送请求

    1.1发送get请求

    from urllib3 import *
    # urlencode函数在urllib.parse模块中
    from urllib.parse import urlencode
    # 调用disable_warnings函数可以阻止显示警告消息
    disable_warnings()
    # 创建PoolManager类的实例
    http = PoolManager()
    '''
    # 下面的代码通过组合URL的方式向百度发送请求
    url = 'http://www.baidu.com/s?' + urlencode({'wd':'极客起源'})
    print(url)
    response = http.request('GET', url)
    '''
    url = 'http://www.baidu.com/s'
    # 直接使用fields关键字参数指定GET请求字段
    response = http.request('GET', url,fields={'wd':'极客起源'})
    # 获取百度服务端的返回值(字节形式),并使用UTF-8格式对其进行解码
    data = response.data.decode('UTF-8')
    # 输出百度服务端返回的内容
    print(data)
    

    1.2发送HTTP POST请求

    首先用flask模块编写个可以处理HTTP POST请求的服务端程序

    # 支持HTTP POST请求的服务端程序
    from flask import Flask, request
    # 创建Flask对象,任何基于flask模块的服务端应用都必须创建Flask对象
    app = Flask(__name__)
    # 设置/register路由,该路由可以处理HTTP POST请求
    @app.route('/register', methods=['POST'])
    def register():
        # 输出名为name的请求字字段的值
        print(request.form.get('name'))
        # 输出名为age的请求字段的值
        print(request.form.get('age'))
        # 向客户端返回“注册成功”消息
        return '注册成功'
    
    if __name__ == '__main__':
        # 开始运行服务端程序,默认端口号是5000
        app.run()
    

    然后在使用urllib3中相应的API向这个服务端程序发送HTTP POST请求,然后输出服务端的返回结果

    from urllib3 import *
    disable_warnings()
    http = PoolManager()
    # 指定要提交HTTP POST请求的URL,/register是路由
    url = 'http://localhost:5000/register'
    # 向服务端发送HTTP POST请求,用fields关键字参数指定HTTP POST请求字段名和值
    response = http.request('POST', url,fields={'name':'李宁','age':18})
    # 获取服务端返回的数据
    data = response.data.decode('UTF-8')
    # 输出服务端返回的数据
    print(data)
    

    二.设置HTTP请求头

    1.HTTP请求头

    大多数服务端应用都会检测某些HTTP请求头,还有一些服务端应用要求只有处于登录状态才可以访问某些数据,所以需要检测HTTP请求头的Cookie字段,该字段会包含标识用户登录的信息。
    通过PoolManager对象的request方法的headers关键字参数可以指定字典形式的HTTP请求头

    response = http.request('GET', url,headers=headers)
    

    详细代码如下,通过request方法访问了天猫商城的搜索功能

    from urllib3 import *
    import re
    disable_warnings()
    http = PoolManager()
    # 定义天猫的搜索页面URL
    #url = 'https://list.tmall.com/search_product.htm?spm=a220m.1000858.1000724.4.53ec3e72bTyQhM&q=%D0%D8%D5%D6&sort=d&style=g&from=mallfp..pc_1_searchbutton#J_Filter'
    url = 'http://httpbin.org/get'
    # 从headers.txt文件读取HTTP请求头,并将其转换为字典形式
    def str2Headers(file):
        headerDict = {}
        f = open(file,'r')
        # 读取headers.txt文件中的所有内容
        headersText = f.read() # 文件读取出来看样子是一下子全部读取出来,才有之后的分隔操作,类型因该是字符串
        print(type(headersText)) # <class 'str'>
        print('read出来的样子是什么',headersText)
        headers = re.split('
    ',headersText) # 以换行符进行分隔
        for header in headers:
            result = re.split(':',header,maxsplit = 1) # 以冒号进行分隔
            headerDict[result[0]] = result[1] # 写入字典
        f.close()
        # print(headerDict)
        return headerDict
    headers = str2Headers('headers.txt')
    # 请求天猫的搜索页面,并传递HTTP请求头
    response = http.request('GET', url,headers=headers)
    # 将服务端返回的数据按GB18030格式解码
    data = response.data.decode('GB18030')
    print(data)
    

    三.获取HTTP响应头

    1.使用HTTPresponse.info()方法可以很容易获取HTTP响应头的信息

    from urllib3 import *
    disable_warnings()
    http = PoolManager()
    url = 'https://www.baidu.com'
    response = http.request('GET', url)
    # # 输出HTTP响应头信息(以字典形式返回HTTP响应头信息)
    for key in response.info().keys(): # keys()就是在外面嵌套了一层皮,
        print(key,':', response.info()[key])
    
    print('-'*10,'分割线','-'*10)
    
    print(response.info().keys()) 
    print(type(response.info().keys())) # <class 'collections.abc.KeysView'>差不多十个可迭代对象
    
    print('-'*10,'分割线','-'*10)
    print(response.info())
    print(type(response.info())) # <class 'urllib3._collections.HTTPHeaderDict'>
    
    

    四.上传文件

    只需设置普通的HTTP请求头一样在request方法中使用fields关键字参数指定一个描述上传文件的HTTP请求头字段,然后再通过元组指定相关属性即可,例如:上传的文件名,文件类型

    4.1编写一个可以将文件上传到服务端的Python程序,可以通过输入本地文件名来上传任何类型的文件

    import os
    from flask import Flask, request
    # 定义服务端保存上传文件的位置
    UPLOAD_FOLDER = 'uploads'
    app = Flask(__name__)
    
    # 用于接收上传文件的路由需要使用POST方法
    @app.route('/', methods=['POST'])
    def upload_file():
        # 获取上传文件的内容
        file = request.files['file'] # files字段
        if file:
            # 这里的save函数又是什么
            # 将上传的文件保存到uploads子目录中;
            # 这个是把后面的文件加到前面文件夹中么
            file.save(os.path.join(UPLOAD_FOLDER, os.path.basename(file.filename)))
            return "文件上传成功"
    
    if __name__ == '__main__':
        app.run()
    
    

    4.2编写上传文件的客户端程序

    上传文件的编写也有很多讲究

    from urllib3 import *
    disable_warnings()
    http = PoolManager()
    # 定义上传文件的服务端Url
    url = 'http://localhost:5000'
    while True: # 这里还是无限循环的上传
        # 输入上传文件的名字
        filename = input('请输入要上传的文件名字(必须在当前目录下):')
        # 如果什么也未输入,退出循环
        if not filename:
            break
        # 用二进制的方式打开要上传的文件名,然后读取文件的所有内容,使用with语句会自动关闭打开的文件
        with open(filename,'rb') as fp:
            fileData = fp.read()
        # 上传文件
        response = http.request('POST',url,fields={'file':(filename,fileData)})
        # 输出服务端的返回结果,本例是“文件上传成功”
        print(response.data.decode('utf-8'))
    
    

    五.超时

    由于HTTP底层是基于Scoket实现的,所以连接的过程也可能超时,Scoket超时分为连接超时和读超时
    需要通过request方法的timeout关键字参数指定超时时间即可
    通过PoolManager类的构造方法指定默认的连接超时和读超时

    from urllib3 import *
    disable_warnings()
    # 通过PoolManager类的构造方法指定默认的连接超时和读超时
    http = PoolManager(timeout=Timeout(connect=2.0,read=2.0))
    url1 = 'https://www.baidu1122.com'
    url2 = 'http://httpbin.org/delay/3'
    try:
    # 此处代码需要放在try…except中,否则一旦抛出异常,后面的代码将无法执行
    # 下面的代码会抛出异常,因为域名www.baidu1122.com并不存在
    # 由于连接超时设为2秒,
        http.request('GET', url1,timeout=Timeout(connect=2.0,read=4.0))
    except Exception as e:
        print(e)
    print('------------')
    # 由于读超时为4秒,而url2指定的Url在3秒后就返回数据,所以不会抛出异常,
    # 会正常输出服务器的返回结果
    response = http.request('GET', url2,timeout=Timeout(connect=2.0,read=4.0))
    print(response.info())
    print('------------')
    print(response.info()['Content-Length'])
    # 由于读超时为2秒,所以会在2秒后抛出读超时异常
    http.request('GET', url2,timeout=Timeout(connect=2.0,read=2.0))
    
    努力拼搏吧,不要害怕,不要去规划,不要迷茫。但你一定要在路上一直的走下去,尽管可能停滞不前,但也要走。
  • 相关阅读:
    HDU 2639 Bone Collector II (01背包,第k解)
    POJ 2184 Cow Exhibition 奶牛展(01背包,变形)
    hihoCoder #1165 : 益智游戏 (挑战赛11 B题)
    UVA 562 Dividing coins 分硬币(01背包,简单变形)
    POJ Charm Bracelet 挑饰品 (常规01背包)
    hiho一下 第四十四周 博弈游戏·Nim游戏(直接公式解)
    UVA 624 CD(01背包,要记录路径)
    118 Pascal's Triangle 帕斯卡三角形 杨辉三角形
    117 Populating Next Right Pointers in Each Node II 每个节点的右向指针 II
    116 Populating Next Right Pointers in Each Node 每个节点的右向指针
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/15227613.html
Copyright © 2011-2022 走看看