Request的高级用法

文件上传

我们知道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)
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,260评论 19 139
  • Getting Started Burp Suite 是用于攻击web 应用程序的集成平台。它包含了许多工具,并为...
    Eva_chenx阅读 29,155评论 0 14
  • 上一篇:8.Urllib库基本使用下一篇:10.正则表达式基础 requests是python实现的最简单易用的H...
    在努力中阅读 8,820评论 2 11
  • 目录Cookie机制什么是CookieCookie的不可跨域名性Unicode编码:保存中文BASE64编码:保存...
    Tomatoro阅读 17,025评论 7 186
  • 会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Se...
    chinariver阅读 10,982评论 1 49

友情链接更多精彩内容