爬虫笔记四
一、Requests快速入门
1.发送请求
import requests # 常见的请求方式 get post r = requests.get('https://github.com/timeline.json') # r = requests.post("http://httpbin.org/post") print(r.text) print(r.url) # 其它请求方式 # 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")
2.传递URL参数
手工构建的 URL,那么数据会以键/值对的形式置于 URL 中,跟在一个问号的后面。例如, httpbin.org/get?key=val
。
Requests 允许你使用 params
关键字参数,以一个字符串字典来提供这些参数。
如果你想传递 key1=value1
和 key2=value2
到 httpbin.org/get
,那么你可以使用如下代码:
import requests payload = {'key1':'values1','key2':'values2'} r = requests.get(url='http://httpbin.org/get',params=payload) # params= 用来在URL中传递键值对参数 ?后面进行拼接 ?key1=values1&key2=values2 print(r.url) # http://httpbin.org/get?key1=values1&key2=values2 # 注意字典里值为 None 的键都不会被添加到 URL 的查询字符串 # 参数中的值可以是一个列表 payload = {'key1':'values1','key2':['values2','values3']} r = requests.get(url='http://httpbin.org/get',params=payload) print(r.url) # http://httpbin.org/get?key1=values1&key2=values2&key2=values3
3.响应内容
Requests 会自动解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。
import requests r = requests.get(url='https://github.com/timeline.json') # 默认是utf8编码 r.encoding = 'gbk' # 改变编码
4.Json响应内容
Requests 中也有一个内置的 JSON 解码器,助你处理 JSON 数据。
需要注意的是,成功调用 r.json()
并**不**意味着响应的成功。有的服务器会在失败的响应中包含一个 JSON 对象(比如 HTTP 500 的错误细节)。这种 JSON 会被解码返回。要检查请求是否成功,请使用 r.raise_for_status()
或者检查 r.status_code
是否和你的期望相同。
r.json( )
5.定制请求头
如果你想为请求添加 HTTP 头部,只要简单地传递一个 dict
给 headers
参数就可以了。
import requests url = 'https://api.github.com/some/endpoint' headers = {'user-agent': 'my-app/0.0.1'} r = requests.get(url, headers=headers)
所有的 header 值必须是 string
、bytestring 或者 unicode。
尽管传递 unicode header 也是允许的,但不建议这样做。
6.更加复杂的POST请求
想要发送一些编码为表单形式的数据——非常像一个 HTML 表单。只需简单地传递一个字典给 data 参数。你的数据字典在发出请求时会自动编码为表单形式
import requests payload = {'key1': 'value1', 'key2': 'value2'} r = requests.post("http://httpbin.org/post", data=payload) print(r.text) ''' { "args": {}, "data": "", "files": {}, "form": { "key1": "value1", "key2": "value2" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "23", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.4" }, "json": null, "origin": "61.184.75.210", "url": "http://httpbin.org/post" } '''
为 data
参数传入一个元组列表。在表单中多个元素使用同一 key 的时候,这种方式尤其有效:
import requests payload = (('key1', 'value1'), ('key1', 'value2')) r = requests.post("http://httpbin.org/post", data=payload) print(r.text) ''' { "args": {}, "data": "", "files": {}, "form": { "key1": [ "value1", "value2" ] }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "23", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.4" }, "json": null, "origin": "61.184.75.210", "url": "http://httpbin.org/post" } '''
很多时候你想要发送的数据并非编码为表单形式的。如果你传递一个 string
而不是一个 dict
,那么数据会被直接发布出去。
import requests import json url = 'https://api.github.com/some/endpoint' payload = {'some': 'data'} r = requests.post(url, data=json.dumps(payload)) # r = requests.post(url, json=payload)
7.响应状态码
import requests r = requests.get('http://httpbin.org/get') print(r.status_code) # 200
8.响应头
我们可以查看以一个 Python 字典形式展示的服务器响应头:
import requests r = requests.get('http://httpbin.org/get') print(r.headers) ''' { 'Connection': 'keep-alive', 'Server': 'meinheld/0.6.1', 'Date': 'Tue, 09 Jan 2018 07:00:48 GMT', 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true', 'X-Powered-By': 'Flask', 'X-Processed-Time': '0.000684976577759', 'Content-Length': '266', 'Via': '1.1 vegur' } '''
它还有一个特殊点,那就是服务器可以多次接受同一 header,每次都使用不同的值。
9.Cookie
要想发送你的cookies到服务器,可以使用 cookies
参数:
import requests url = 'http://httpbin.org/cookies' cookies = dict(cookies_are='working') r = requests.get(url, cookies=cookies) print(r.text) ''' { "cookies": { "cookies_are": "working" } } '''
Cookie 的返回对象为 RequestsCookieJar
,它的行为和字典类似,但界面更为完整,适合跨域名跨路径使用。你还可以把 Cookie Jar 传到 Requests 中:
import requests jar = requests.cookies.RequestsCookieJar() jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies') jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere') url = 'http://httpbin.org/cookies' r = requests.get(url, cookies=jar) print(r.text) ''' { "cookies": { "tasty_cookie": "yum" } } '''
10重定向和请求历史
默认情况下,除了 HEAD, Requests 会自动处理所有重定向。
可以使用响应对象的 history
方法来追踪重定向。
Response.history
是一个 Response
对象的列表,为了完成请求而创建了这些对象。这个对象列表按照从最老到最近的请求进行排序。
import requests r = requests.get('http://github.com') print(r.url) # https://github.com/ print(r.status_code) # 200 print(r.history) # [<Response [301]>]
如果你使用的是GET、OPTIONS、POST、PUT、PATCH 或者 DELETE,那么你可以通过 allow_redirects
参数禁用重定向处理:
import requests # allow_redirects=False 禁用重定向 r = requests.get('http://github.com', allow_redirects=False) print(r.url) # http://github.com/ print(r.status_code) # 301 print(r.history) # []
如果你使用了 HEAD,你也可以启用重定向:
import requests r = requests.head('http://github.com', allow_redirects=True) print(r.url) # https://github.com/ print(r.status_code) # 200 print(r.history) # [<Response [301]>]
11.超时
你可以告诉 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) 注意 timeout 仅对连接过程有效,与响应体的下载无关。 timeout 并不是整个下载响应的时间限制,而是如果服务器在 timeout 秒内没有应答,将会引发一个异常(更精确地说,是在 timeout 秒内没有从基础套接字上接收到任何字节的数据时)If no timeout is specified explicitly, requests do not time out.
12.错误与异常
遇到网络问题(如:DNS 查询失败、拒绝连接等)时,Requests 会抛出一个 ConnectionError
异常。
如果 HTTP 请求返回了不成功的状态码, Response.raise_for_status()
会抛出一个 HTTPError
异常。
若请求超时,则抛出一个 Timeout
异常。
若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects
异常。
所有Requests显式抛出的异常都继承自 requests.exceptions.RequestException
。