美文网首页
Request的高级用法

Request的高级用法

作者: 冰度猎魂 | 来源:发表于2018-12-09 00:18 被阅读0次

    文件上传

    我们知道requests可以模拟提交一些数据。例如有的网站需要上传文件,我们也可以用它来实现,这非常简单,示例如下:

    import requests
    
    files = {'file': open('favicon.ico', 'rb')}
    r = requests.post("http://httpbin.org/post", files=files)
    print(r.text)
    

    需要注意的是,favicon.ico需要和当前脚本在同一目录下。

    {
      "args": {}, 
      "data": "", 
      "files": {
        "file": "data:application/octet-stream;base64,AAAAAA...="
      }, 
      "form": {}, 
      "headers": {
        "Accept": "*/*", 
        "Accept-Encoding": "gzip, deflate", 
        "Connection": "close", 
        "Content-Length": "147", 
        "Content-Type": "multipart/form-data; boundary=cff98377c65b22dea6b6b8843808f361", 
        "Host": "httpbin.org", 
        "User-Agent": "python-requests/2.19.1"
      }, 
      "json": null, 
      "origin": "114.245.27.179", 
      "url": "http://httpbin.org/post"
    }
    

    这个网站会返回响应,里面包含files这个字段,而form字段是空,这证明文件上传部分会单独有一个files字段来标识。

    Cookies

    requests获取和设置Coolies只需一步即可完成。

    import requests
    
    r = requests.get("https://www.baidu.com")
    print(r.cookies)
    for key, value in r.cookies.items():
        print(key + '=' + value)
    

    运行结果如下:

    <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
    BDORZ=27315
    

    这里我们首先调用cookies属性即可成功得到Cookies,可以发现它是RequestCookieJar类型。然后用items()方法将其转化为元组组成的列表,遍历输出每一个Cookie的名称和值,实现Cookie的遍历解析。

    import requests
    
    cookies = 'tgw_l7_route=860ecf76daf7b83f5a2f2dc22dccf049; _xsrf=vUuULqZA3FFmjIlhgE5QhQ5wqevPchwo; _zap=4947505c-3f0a-461c-9919-fc6774bd8bf0; d_c0="AHBiiWOtow6PTpwNxwmtRvBUzk8GoRnpN9A=|1544282366"; capsion_ticket="2|1:0|10:1544282386|14:capsion_ticket|44:MzQ5ZGMzMmNkZGQ3NDRiNThhODU4MjhjZTk2NDgxZjk=|303e46b9907dc5d0ed9ed6b4758b0117d5461a9fac16b7acdab44493ee0b56c7"; z_c0="2|1:0|10:1544282414|4:z_c0|92:Mi4xQ3d3ekNBQUFBQUFBY0dLSlk2MmpEaVlBQUFCZ0FsVk5MaV81WEFBOGVhaVBOYjhGYlBqZGlLamFOQnRRQ2NabDNn|3b2f2d0cab10c69f39091a3ff3742ac64d873547469927661fc1e4fcb926faa1"; tst=r; q_c1=d0a3c796b1364af9adc18022877142eb|1544282423000|1544282423000'
    jar = requests.cookies.RequestsCookieJar()
    headers = {
        'Host': 'www.zhihu.com',
        'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36'
    }
    for cookie in cookies.split(';'):
        key, value = cookie.split('=', 1)
        jar.set(key, value)
    r = requests.get("http://www.zhihu.com", cookies=jar, headers=headers)
    print(r.text)
    

    这里我们首先新建了一个RequestCookieJar对象,然后将复制下来的cookies利用split()方法分割,接着利用set()方法设置好每个Cookie的key和value,然后通过调用requests的get()方法并传递给cookies参数即可。当然,由于知乎本身的限制,headers参数也不能少,只不过不需要在原来的headers参数里面设置cookie字段了。
    测试后,发现同样可以正常登录知乎。

    会话维持

    在requests中,如果直接利用get()或post()等方法的确可以做到模拟网页的请求,但是这实际上相当于不同的会话,也就是说相当于你用了两个浏览器打开了不同的页面。
    利用Session,我们可以方便地维护一个会话,而且不用担心cookies的问题,它会帮我们自动处理好。

    import requests
    
    requests.get('http://httpbin.org/cookies/set/number/123456789')
    r = requests.get('http://httpbin.org/cookies')
    print(r.text)
    

    使用如上所示代码,并不能成功设置Cookies。

    import requests
    
    s = requests.Session()
    s.get('http://httpbin.org/cookies/set/number/123456789')
    r = s.get('http://httpbin.org/cookies')
    print(r.text)
    

    运行结果如下:

    {
      "cookies": {
        "number": "123456789"
      }
    }
    

    所以,利用Session,可以做到模拟同一个会话而不用担心Cookies的问题。它通常用于模拟登录成功之后再进行下一步的操作。

    SSL证书验证

    此外,requests还提供了证书验证的功能。当发送HTTP请求的时候,它会检查SSL证书,我们可以使用verify参数控制是否检查此证书。其实如果不加verify参数的话,默认是True,会自动验证。

    import requests
    
    response = requests.get('https://www.12306.cn')
    print(response.status_code)
    

    运行结果如下(这是之前的验证结果,现在12306的证书已经可以验证了,会返回200):

    requests.exceptions.SSLError:("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",)
    

    这里提示一个错误SSLError,表示证书验证错误。所以,如果请求一个HTTPS站点,但是证书验证错误的页面时,就会报这样的错误,那么如何避免这个错误呢?只需要把verify参数设置为False即可。

    import requests
    
    response = requests.get('https://www.12306.cn', verify=False)
    print(response.status_code)
    

    这样就会打印出请求成功的状态码:

    lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
      InsecureRequestWarning)
    lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
    200
    

    不过我们发现了一个警告,它建议我们给它制定证书。我们可以通过设置忽略警告的方式来屏蔽这个警告:

    import requests
    from requests.packages import urllib3
    
    urllib3.disable_warnings()
    response = requests.get('https://www.12306.cn', verify=False)
    print(response.status_code)
    

    或者通过捕获警告到日志的方式忽略警告:

    import logging
    import requests
    logging.captureWarnings(True)
    response = requests.get('https://www.12306.cn', verify=False)
    print(response.status_code)
    

    当然,我们也可以指定一个本地证书用作客户端证书,这可以是单个文件(包含密钥和证书)或一个包含两个文件路径的元组:

    import requests
    
    response = requests.get('https//www.12306.cn', cert=('/path/server.crt', '/path/key'))
    print(response.status_code)
    

    当然,上面的代码是演示实例,我们需要有crt和key文件,并且指定它们的路径。注意,本地私有证书的key必须是解密状态,加密状态的key是不支持的。

    超时设置

    在本机网络状态不好或者服务器网络响应太慢甚至无响应时,我们可能会等待特别久的时间才可能受到响应,甚至到最后收不到响应而报错。为了防止服务器不能及时响应,应该设置一个超时时间,即超过了这个时间还没有得到响应,那就报错。这需要用到timeout参数。这个时间的计算是发出请求到服务器返回响应的时间。示例如下:

    import requests
    
    r = requests.get("https://www.taobao.com", timeout=1)
    print(r.status_code)
    

    通过这样的方式,我们可以将超时时间设置为1秒,如果1秒内没有响应,那就抛出异常。
    实际上,请求分为两个阶段,即连接和读取。
    上面设置的timeout将用作连接和读取二者的timeout总和。
    如果要分别指定,就可以传入一个元组:

    r = requests.get('https://www.taobao.com', timeout=(5, 11, 30))
    

    如果想永久等待,可以直接将timeout设置为None,或者不设置直接留空,因为默认是None。这样的话,如果服务器还在运行,但是响应特别慢,那就慢慢等吧,它永远不会返回超时错误的。

    r = requests.get('https://www.taobao.com', timeout=None)
    

    相关文章

      网友评论

          本文标题:Request的高级用法

          本文链接:https://www.haomeiwen.com/subject/vwichqtx.html