• 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))
    
    努力拼搏吧,不要害怕,不要去规划,不要迷茫。但你一定要在路上一直的走下去,尽管可能停滞不前,但也要走。
  • 相关阅读:
    嘀嘀咕 (1)
    碎碎念(4)
    渲染层错误] TypeError: Cannot read property 'replace' of undefined at rewrit
    怎么跳出foreach
    vs code的Go Live不出现
    ES6
    h5分享到微信,分享到朋友圈
    网页之间传值与获取值
    原生js添加节点的高级简便写法
    原型链
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/15227613.html
Copyright © 2020-2023  润新知