宽屏模式

python第三方模块requests的使用--初级

requests 使用;

导入模块:import requests
获取某个网页:r = requests.get('https://api.github.com/events')

传递参数

payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)
# 通过打印输出该 URL,你能看到 URL 已被正确编码:
print(r.url) # http://httpbin.org/get?key2=value2&key1=value1

# 注意:字典里值为 None 的键不会被添加到 URL 的查询字符中

# 还可以将一个列表作为值传入
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.get('http://httpbin.org/get', params=payload)
print(r.url) # http://httpbin.org/get?key1=value1&key2=value2&key2=value3

响应内容

import requests
r = requests.get('https://api.github.com/events')
print(r.text) # u'[{"repository":{"open_issues":0,"url":"https://github.com/...

# 获取requests使用的编码
print(r.encoding)

# 改变编码
r.encoding = 'ISO-8859-1'
#requests还可以使用定制的编码,如果你创建了自己的编码的话;
#可以使用codecs进行注册,然后使用这个解码器作为r.encoding的值,然后使用requests为你处理编码;

Requests 会自动解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。

二进制响应内容

#以字节方式请求响应体
>>>r.content
b'[{"repository":{"open_issues":0,"url":"https://github.com/...

Requests 会自动为你解码 gzip 和 deflate 传输编码的响应数据。

以请求返回的二进制数据创造一张图片:

>>> from PIL import Image
>>> from io import BytesIO

>>> i = Image.open(BytesIO(r.content))

JSON 响应内容

requests 中内置了一个json解码器:

r.json()

如果r.json()解码失败,就会抛出异常;

成功调用r.json()并不代表响应成功;

想知道响应成功与否,可以使用 r.raise_for_status() 或者检查 r.status_code 是否和你的期望相同;

原始响应内容

当你想获取来自服务器的原始套接字响应,那么你可以访问r.raw
前提是,你在初始请求中设置了stream=True

>>> r = requests.get('https://api.github.com/events', stream=True)
>>> 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)

请求头定制

要想定制请求头的话,直接传递一个dict给headers参数就可以;

>>> url = 'https://api.github.com/some/endpoint'
>>> headers = {'user-agent': 'my-app/0.0.1'}

>>> r = requests.get(url, headers=headers)

注意: 定制 header 的优先级低于某些特定的信息源,例如:

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

Requests 不会基于定制 header 的具体情况改变自己的行为。
注意: 所有的 header 值必须是 string、bytestring 或者 unicode。尽管传递 unicode header 也是允许的,但不建议这样做。

更加复杂的 POST 请求

若要传递类似表单的数据,只需要给data参数传递一个dict就可以;

>>> payload = {'key1': 'value1', 'key2': 'value2'}

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

还可以为data参数传入一个元组(在表单中多个元素使用同一个key);

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

若你,想发送的数据并非编码为表单形式的;
如果你传递一个 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))

在 2.4.2 版中,你可以直接使用json参数直接传递,无需编码后再传给data参数;

>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, json=payload)

POST一个多部分编码(Multipart-Encoded)的文件(上传文件或图片)

>>> 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"
  },
  ...
}

如果你发送一个非常大的文件作为 multipart/form-data 请求,你可能希望将请求做成数据流。默认下 requests 不支持, 但有个第三方包 requests-toolbelt 是支持的。

**警告**
强烈建议你用二进制模式(binary mode)打开文件。这是因为 Requests 可能会试图为你提供 Content-Length header,在它这样做的时候,这个值会被设为文件的字节数(bytes)。如果用文本模式(text mode)打开文件,就可能会发生错误。

响应状态码

status_code 可以检测响应状态码;

>>> r = requests.get('http://httpbin.org/get')
>>> r.status_code
200

为方便引用,Requests还附带了一个内置的状态码查询对象:
r.status_code == requests.codes.ok # True
如果发送了一个错误请求(一个 4XX 客户端错误,或者 5XX 服务器错误响应),我们可以通过 Response.raise_for_status() 来抛出异常:

>>> bad_r = requests.get('http://httpbin.org/status/404')
>>> bad_r.status_code
404

>>> bad_r.raise_for_status()
Traceback (most recent call last):
  File "requests/models.py", line 832, in raise_for_status
    raise http_error
requests.exceptions.HTTPError: 404 Client Error

快速上手requests

Larwas
请先登录后发表评论
  • latest comments
  • 总共0条评论