python爬⾍开发之Request模块从安装到详细使⽤⽅法与
实例全解
python爬⾍模块Request的安装
在cmd中,使⽤如下指令安装requests:
pip install requests
python爬⾍模块Request快速上⼿
Requests 已安装
Requests 是最新的
Request模块发送请求
使⽤ Requests 发送⽹络请求⾮常简单。
⼀开始要导⼊ Requests 模块:
>>> import requests
然后,尝试获取某个⽹页。本例⼦中,我们来获取 Github 的公共时间线:
>>> r = ('api.github/events')
现在,我们有⼀个名为 r 的 Response 对象。我们可以从这个对象中获取所有我们想要的信息。
Requests 简便的 API 意味着所有 HTTP 请求类型都是显⽽易见的。例如,你可以这样发送⼀个 HTTP POST 请求:
>>> r = requests.post('/post', data = {'key':'value'})
那么其他 HTTP 请求类型:PUT,DELETE,HEAD 以及 OPTIONS ⼜是如何的呢?都是⼀样的简单:
>>> r = requests.put('/put', data = {'key':'value'})
>>> r = requests.delete('/delete')
>>> r = requests.head('/get')
>>> r = requests.options('/get')
Request模块传递URL参数
你也许经常想为 URL 的查询字符串(query string)传递某种数据。如果你是⼿⼯构建 URL,那么数据会以键/值对的形式置于URL 中,跟在⼀个问号的后⾯。
例如, /get?key=val。 Requests 允许你使⽤ params 关键字参数,以⼀个字符串字典来提供这些参数。举例来说,如果你想传递 key1=value1 和 key2=value2 到 /get ,那么你可以使⽤如下代码:
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = ("/get", params=payload)
通过打印输出该 URL,你能看到 URL 已被正确编码:
>>> print(r.url)
/get?key2=value2&key1=value
注意字典⾥值为 None 的键都不会被添加到 URL 的查询字符串⾥。
你还可以将⼀个列表作为值传⼊:
>>> payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
>>> r = ('/get', params=payload)
>>> print(r.url)
/get?key1=value1&key2=value2&key2=value
Request模块响应内容
我们能读取服务器响应的内容。再次以 GitHub 时间线为例:
>>> import requests
>>> r = ('api.github/events')
>>> r.text
u'[{"repository":{"open_issues":0,"url":"github/...
Requests会⾃动解码来⾃服务器的内容。⼤多数 unicode 字符集都能被⽆缝地解码。
请求发出后,Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。
当你访问 r.text 之时,Requests 会使⽤其推测的⽂本编码。
你可以出 Requests 使⽤了什么编码,并且能够使⽤ r.encoding 属性来改变它:
>>> r.encoding
'utf-8'
>>> r.encoding = 'ISO-8859-1'
如果你改变了编码,每当你访问 r.text ,Request 都将会使⽤ r.encoding 的新值。
你可能希望在使⽤特殊逻辑计算出⽂本的编码的情况下来修改编码。⽐如 HTTP 和 XML ⾃⾝可以指定编码。这样的话,你应该使⽤ r.content 来到编码,然后设置 r.encoding 为相应的编码。这样就能使⽤正确的编码解析 r.text 了。
在你需要的情况下,Requests 也可以使⽤定制的编码。如果你创建了⾃⼰的编码,并使⽤ codecs 模块进⾏注册,你就可以轻松地使⽤这个解码器名称作为 r.encoding 的值,然后由 Requests 来为你处理编码。
Request模块⼆进制响应内容
你也能以字节的⽅式访问请求响应体,对于⾮⽂本请求:
>>> r.content
b'[{"repository":{"open_issues":0,"url":"github/...
Requests 会⾃动为你解码 gzip 和 deflate 传输编码的响应数据。
例如,以请求返回的⼆进制数据创建⼀张图⽚,你可以使⽤如下代码:
>>> from PIL import Image
>>> from io import BytesIO
>>> i = Image.open(t))
Request模块JSON 响应内容
Requests 中也有⼀个内置的 JSON 解码器,助你处理 JSON 数据:
>>> import requests
>>> r = ('api.github/events')
>>> r.json()
[{u'repository': {u'open_issues': 0, u'url': 'github/...
如果 JSON 解码失败, r.json() 就会抛出⼀个异常。
例如,响应内容是 401 (Unauthorized),尝试访问 r.json() 将会抛出 ValueError: No JSON object could be decoded 异常。
需要注意的是,成功调⽤ r.json() 并不意味着响应的成功。
有的服务器会在失败的响应中包含⼀个 JSON 对象(⽐如 HTTP 500 的错误细节)。这种 JSON 会被解码返回。要检查请求是否成功,请使⽤ r.raise_for_status() 或者检查 r.status_code 是否和你的期望
相同。
Request模块原始响应内容
在罕见的情况下,你可能想获取来⾃服务器的原始套接字响应,那么你可以访问 r.raw。
如果你确实想这么⼲,那请你确保在初始请求中设置了 stream=True。具体你可以这么做:
>>> r = ('api.github/events', stream=True)
>>> r.raw
<requests.sponse.HTTPResponse object at 0x101194810>
>>> ad(10)
' 1f 8b 08 00 00 00 00 00 00 03'
但⼀般情况下,你应该以下⾯的模式将⽂本流保存到⽂件:
with open(filename, 'wb') as fd:
for chunk in r.iter_content(chunk_size):
fd.write(chunk)
使⽤ Response.iter_content 将会处理⼤量你直接使⽤ Response.raw 不得不处理的。当流下载时,上⾯是优先推荐的获取内容⽅式。 Note that chunk_size can be freely adjusted to a number that may better fit your use cases.
Request模块定制请求头
如果你想为请求添加 HTTP 头部,只要简单地传递⼀个 dict 给 headers 参数就可以了。
>>> url = 'api.github/some/endpoint'
>>> headers = {'user-agent': 'my-app/0.0.1'}
>>> r = (url, headers=headers)
注意: 定制 header 的优先级低于某些特定的信息源,例如:
如果在 rc 中设置了⽤户认证信息,使⽤ headers= 设置的授权就不会⽣效。
如果设置了 auth= 参数,rc 的设置就⽆效了。
如果被重定向到别的主机,授权 header 就会被删除。
代理授权 header 会被 URL 中提供的代理⾝份覆盖掉。
在我们能判断内容长度的情况下,header 的 Content-Length 会被改写。
更进⼀步讲,Requests 不会基于定制 header 的具体情况改变⾃⼰的⾏为。只不过在最后的请求中,所有的 header 信息都会被传递进去。
注意: 所有的 header 值必须是 string、bytestring 或者 unicode。尽管传递 unicode header 也是允许的,但不建议这样做。
Request模块更加复杂的 POST 请求
通常,你想要发送⼀些编码为表单形式的数据——⾮常像⼀个 HTML 表单。
要实现这个,只需简单地传递⼀个字典给 data 参数。你的数据字典在发出请求时会⾃动编码为表单形式:
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("/post", data=payload)
>>> )
{
...
"form": {
"key2": "value2",
"key1": "value1"
},
...
}
你还可以为 data 参数传⼊⼀个元组列表。
在表单中多个元素使⽤同⼀ key 的时候,这种⽅式尤其有效:
>>> payload = (('key1', 'value1'), ('key1', 'value2'))
>>> r = requests.post('/post', data=payload)
>>> )
{
...
"form": {
"key1": [
"value1",
"value2"
]
},
...
}
很多时候你想要发送的数据并⾮编码为表单形式的。
如果你传递⼀个 string ⽽不是⼀个 dict,那么数据会被直接发布出去。
例如,Github API v3 接受编码为 JSON 的 POST/PATCH 数据:
>>> import json
>>> url = 'api.github/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(payload))
此处除了可以⾃⾏对 dict 进⾏编码,你还可以使⽤ json 参数直接传递,然后它就会被⾃动编码
这是 2.4.2 版的新加功能:
>>> url = 'api.github/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, json=payload)
POST⼀个多部分编码(Multipart-Encoded)的⽂件
Requests 使得上传多部分编码⽂件变得很简单:
>>> url = '/post'
>>> files = {'file': open('report.xls', 'rb')}
>>> r = requests.post(url, files=files)
>>> r.text
{
.
..
"files": {
"file": "&data>"
},
...
}
你可以显式地设置⽂件名,⽂件类型和请求头:
>>> url = '/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": "&data>"
},
...
}
如果你想,你也可以发送作为⽂件来接收的字符串:
>>> url = '/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 是⽀持的。你可以阅读 toolbelt ⽂档来了解使⽤⽅法。
在⼀个请求中发送多⽂件参考⾼级⽤法⼀节。
Request模块警告
我们强烈建议你⽤⼆进制模式(binary mode)打开⽂件。这是因为 Requests 可能会试图为你提供 Content-Length header,在它这样做的时候,这个值会被设为⽂件的字节数(bytes)。如果⽤⽂本模式(text mode)打开⽂件,就可能会发⽣错误。
Request模块响应状态码
我们可以检测响应状态码:
>>> r = ('/get')
>>> r.status_code
200
为⽅便引⽤,Requests还附带了⼀个内置的状态码查询对象:
>>> r.status_code == des.ok
True
如果发送了⼀个错误请求(⼀个4XX客户端错误,或者5XX服务器错误响应)
我们可以通过 Response.raise_for_status() 来抛出异常:
>>> bad_r = ('/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
Request模块响应头
我们可以查看以⼀个 Python 字典形式展⽰的服务器响应头:
>>> r.headers
{
'content-encoding': 'gzip',
'transfer-encoding': 'chunked',
'connection': 'close',
'server': 'nginx/1.0.4',
'x-runtime': '148ms',
'etag': '"e1ca502697e5c9317743dc078f67693f"',
'content-type': 'application/json'
}
但是这个字典⽐较特殊:它是仅为 HTTP 头部⽽⽣的。根据 RFC 2616, HTTP 头部是⼤⼩写不敏感的。
因此,我们可以使⽤任意⼤写形式来访问这些响应头字段:
>>> r.headers['Content-Type']
'application/json'
爬虫可以干什么
>>> ('content-type')
'application/json'
它还有⼀个特殊点,那就是服务器可以多次接受同⼀header,每次都使⽤不同的值。但Requests会将它们合并,这样它们就可以⽤⼀个映射来表⽰出来,接收者可以合并多个相同名称的 header 栏位,把它们合为⼀个 “field-name: field-value” 配对,将每个后续的栏位值依次追加到合并的栏位值中,⽤逗号隔开即可,这样做不会改变信息的语义。
Request模块Cookie
如果某个响应中包含⼀些 cookie,你可以快速访问它们:
>>> url = 'example/some/cookie/setting/url'
>>> r = (url)
>>> r.cookies['example_cookie_name']
'example_cookie_value'
要想发送你的cookies到服务器,可以使⽤ cookies 参数:
>>> url = '/cookies'
>>> cookies = dict(cookies_are='working')
>>> r = (url, cookies=cookies)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。