Requests库入门

来源:互联网 发布:淘宝联盟第一个月提现 编辑:程序博客网 时间:2024/06/03 19:26

发送请求

直接发送请求

r = requests.get(“http://httpbin.org/get“)
r = requests.put(“http://httpbin.org/put“)
r = requests.delete(“http://httpbin.org/delete“)
r = requests.head(“http://httpbin.org/get“)
r = requests.options(“http://httpbin.org/get“)

传递URL参数

如果你是手工构建 URL,那么数据会以键/值对的形式置于 URL 中,跟在一个问号的后面。例如, httpbin.org/get?key=val。 Requests 允许你使用 params 关键字参数,以一个字典来提供这些参数。举例来说,如果你想传递 key1=value1 和 key2=value2 到 httpbin.org/get ,那么你可以使用如下代码:

payload = {'key1': 'value1', 'key2': 'value2'}r = requests.get("http://httpbin.org/get", params=payload)print(r.url)http://httpbin.org/get?key2=value2&key1=value1

响应内容

文本响应

属性 描述 r.encoding 返回当前解析编码 r.encoding=”utf-8” 设置当前编码为utf-8 r.text 返回文本文件

Requests 会自动解码来自服务器的内容。

import requestsr = requests.get('https://github.com/timeline.json')r.textu'[{"repository":{"open_issues":0,"url":"https://github.com/...

二进制文件响应

属性 描述 r.content 返回二进制文件

JSON响应

属性 描述 r.json() 返回json格式
import requestsr = requests.get('https://github.com/timeline.json')r.json()[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...

原始数据响应

属性 描述 r.raw 返回原始文件 r.raw.read(10) 读取原始文件 r.iter_content 原始文件迭代器
# 读取文件r = requests.get('https://github.com/timeline.json', stream=True)#设置stream流r.raw<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>r.raw.read(10)'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'# 保存文件with open(filename, 'wb') as fd:    for chunk in r.iter_content(chunk_size):        fd.write(chunk)

定制请求头

url = 'https://api.github.com/some/endpoint'headers = {'user-agent': 'my-app/0.0.1'}r = requests.get(url, headers=headers)

注意:
1.如果在 .netrc 中设置了用户认证信息,使用 headers= 设置的授权就不会生效。而如果设置了 auth= 参数,.netrc 的设置就无效了。
2.如果被重定向到别的主机,授权 header 就会被删除。
3.代理授权 header 会被 URL 中提供的代理身份覆盖掉。
4.在我们能判断内容长度的情况下,header 的 Content-Length 会被改写。

复杂的post请求

表单验证

payload = {'key1': 'value1', 'key2': 'value2'}r = requests.post("http://httpbin.org/post", data=payload)print(r.text){  ...  "form": {    "key2": "value2",    "key1": "value1"  },  ...}

很多时候你想要发送的数据并非编码为表单形式的。如果你传递一个 string 而不是一个 dict,那么数据会被直接发布出去。

例如,Github API v3 接受编码为 JSON 的 POST/PATCH 数据:

>>> import json>>> url = 'https://api.github.com/some/endpoint'>>> payload = {'some': 'data'}>>> r = requests.post(url, data=json.dumps(payload))

此处除了可以自行对 dict 进行编码,你还可以使用 json 参数直接传递,然后它就会被自动编码。这是 2.4.2 版的新加功能:

>>> url = 'https://api.github.com/some/endpoint'>>> payload = {'some': 'data'}>>> r = requests.post(url, json=payload)

上传文件

>>> url = 'http://httpbin.org/post'>>> files = {'file': open('report.xls', 'rb')}>>> r = requests.post(url, files=files)>>> r.text{  ...  "files": {    "file": "<censored...binary...data>"  },  ...}

显式地设置文件名,文件类型和请求头:

>>> url = 'http://httpbin.org/post'>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}>>> r = requests.post(url, files=files)>>> r.text{  ...  "files": {    "file": "<censored...binary...data>"  },  ...}

也可以发送作为文件来接收的字符串:

>>> url = 'http://httpbin.org/post'>>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}>>> r = requests.post(url, files=files)>>> r.text{  ...  "files": {    "file": "some,data,to,send\\nanother,row,to,send\\n"  },  ...}

响应状态码

>>> r = requests.get('http://httpbin.org/get')>>> r.status_code200# Requests还附带了一个内置的状态码查询对象:>>> r.status_code == requests.codes.okTrue

如果发送了一个错误请求(一个 4XX 客户端错误,或者 5XX 服务器错误响应),我们可以通过 Response.raise_for_status() 来抛出异常:

>>> bad_r = requests.get('http://httpbin.org/status/404')>>> bad_r.status_code404>>> bad_r.raise_for_status()Traceback (most recent call last):  File "requests/models.py", line 832, in raise_for_status    raise http_errorrequests.exceptions.HTTPError: 404 Client Error

响应头

>>> r.headers{    'content-encoding': 'gzip',    'transfer-encoding': 'chunked',    'connection': 'close',    'server': 'nginx/1.0.4',    'x-runtime': '148ms',    'etag': '"e1ca502697e5c9317743dc078f67693f"',    'content-type': 'application/json'}>>> r.headers['Content-Type']'application/json'>>> r.headers.get('content-type')'application/json'

Cookie

获得Cookie

>>> url = 'http://example.com/some/cookie/setting/url'>>> r = requests.get(url)>>> r.cookies['example_cookie_name']'example_cookie_value'

发送Cookie

>>> url = 'http://httpbin.org/cookies'>>> cookies = dict(cookies_are='working')>>> r = requests.get(url, cookies=cookies)>>> r.text'{"cookies": {"cookies_are": "working"}}'

重定向与请求历史

默认情况下,除了 HEAD, Requests 会自动处理所有重定向。可以使用响应对象的 history 方法来追踪重定向。
Response.history 是一个 Response 对象的列表,为了完成请求而创建了这些对象。这个对象列表按照从最老到最近的请求进行排序。
例如,Github 将所有的 HTTP 请求重定向到 HTTPS:

>>> r = requests.get('http://github.com')>>> r.url'https://github.com/'>>> r.status_code200>>> r.history[<Response [301]>]

如果你使用的是GET、OPTIONS、POST、PUT、PATCH 或者 DELETE,那么你可以通过 allow_redirects 参数禁用重定向处理:

>>> r = requests.get('http://github.com', allow_redirects=False)>>> r.status_code301>>> r.history[]

如果你使用了 HEAD,你也可以启用重定向:

>>> r = requests.head('http://github.com', allow_redirects=True)>>> r.url'https://github.com/'>>> r.history[<Response [301]>]

超时

你可以告诉 requests 在经过以 timeout 参数设定的秒数时间之后停止等待响应:

>>> requests.get('http://github.com', timeout=0.001)Traceback (most recent call last):  File "<stdin>", line 1, in <module>requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)

回话对象 requests.Session()

跨请求保持一些 cookie:

s = requests.Session()s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')r = s.get("http://httpbin.org/cookies")print(r.text)# '{"cookies": {"sessioncookie": "123456789"}}'

会话也可用来为请求方法提供缺省数据。这是通过为会话对象的属性提供数据来实现的:

s = requests.Session()s.auth = ('user', 'pass')s.headers.update({'x-test': 'true'})# both 'x-test' and 'x-test2' are sents.get('http://httpbin.org/headers', headers={'x-test2': 'true'})

不过需要注意,就算使用了会话,方法级别的参数也不会被跨请求保持。下面的例子只会和第一个请求发送 cookie ,而非第二个:

s = requests.Session()r = s.get('http://httpbin.org/cookies', cookies={'from-my': 'browser'})print(r.text)# '{"cookies": {"from-my": "browser"}}'r = s.get('http://httpbin.org/cookies')print(r.text)# '{"cookies": {}}'

如果你要手动为会话添加 cookie,就是用 Cookie utility 函数 来操纵 Session.cookies。
会话还可以用作前后文管理器:

with requests.Session() as s:    s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')

请求与响应对象

任何时候调用 requests.*() 你都在做两件主要的事情。其一,你在构建一个 Request 对象, 该对象将被发送到某个服务器请求或查询一些资源。其二,一旦 requests 得到一个从 服务器返回的响应就会产生一个 Response 对象。该响应对象包含服务器返回的所有信息, 也包含你原来创建的 Request 对象。如下是一个简单的请求,从 Wikipedia 的服务器得到 一些非常重要的信息:

>>> r = requests.get('http://en.wikipedia.org/wiki/Monty_Python')

如果想访问服务器返回给我们的响应头部信息,可以这样做:

>>> r.headers{'content-length': '56170', 'x-content-type-options': 'nosniff', 'x-cache':'HIT from cp1006.eqiad.wmnet, MISS from cp1010.eqiad.wmnet', 'content-encoding':'gzip', 'age': '3080', 'content-language': 'en', 'vary': 'Accept-Encoding,Cookie','server': 'Apache', 'last-modified': 'Wed, 13 Jun 2012 01:33:50 GMT','connection': 'close', 'cache-control': 'private, s-maxage=0, max-age=0,must-revalidate', 'date': 'Thu, 14 Jun 2012 12:59:39 GMT', 'content-type':'text/html; charset=UTF-8', 'x-cache-lookup': 'HIT from cp1006.eqiad.wmnet:3128,MISS from cp1010.eqiad.wmnet:80'}

然而,如果想得到发送到服务器的请求的头部,我们可以简单地访问该请求:

>>> r.request.headers{'Accept-Encoding': 'identity, deflate, compress, gzip','Accept': '*/*', 'User-Agent': 'python-requests/0.13.1'}

准备的请求

当你从 API 或者会话调用中收到一个 Response 对象时,request 属性其实是使用了 PreparedRequest。有时在发送请求之前,你需要对 body 或者 header (或者别的什么东西)做一些额外处理,下面演示了一个简单的做法:

from requests import Request, Sessions = Session()req = Request('GET', url,    data=data,    headers=header)prepped = req.prepare()# do something with prepped.body# do something with prepped.headersresp = s.send(prepped,    stream=stream,    verify=verify,    proxies=proxies,    cert=cert,    timeout=timeout)print(resp.status_code)

由于你没有对 Request 对象做什么特殊事情,你立即准备和修改了 PreparedRequest 对象,然后把它和别的参数一起发送到 requests.* 或者 Session.*。

然而,上述代码会失去 Requests Session 对象的一些优势, 尤其 Session 级别的状态,例如 cookie 就不会被应用到你的请求上去。要获取一个带有状态的 PreparedRequest, 请用 Session.prepare_request() 取代 Request.prepare() 的调用,如下所示:

from requests import Request, Sessions = Session()req = Request('GET',  url,    data=data    headers=headers)prepped = s.prepare_request(req)# do something with prepped.body# do something with prepped.headersresp = s.send(prepped,    stream=stream,    verify=verify,    proxies=proxies,    cert=cert,    timeout=timeout)print(resp.status_code)

SSL证书验证

CA证书

响应体内容工作流

保持活动状态(持久连接)

流式上传

块编码请求

POST 多个分块编码的文件

事件挂钩

自定义身份验证

流式请求

代理

SOCKS