Python requests模块

Python里有自带的 urllib 库,提供了许多强大的功能来获取URL信息,而 urllib2 则提供了一组基于请求(request)的功能.两者可以相铺相成.而今天的主角是第三方库 requests ,其以简单的方式去获取URL,复杂性没有urllib高

获取requests

最简单的方法就是 pip install requests ,然后就可以使用了

发送请求

首先,需要导入 Requests 模块,这里就介绍 get 函数

1
2
3
4
5
6
7
8
9
10
def get(url, params=None, **kwargs):
r"""Sends a GET request.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
kwargs.setdefault('allow_redirects', True)
return request('get', url, params=params, **kwargs)

可以看到 requests.get 函数 实际是调用了 requests.Request 构造请求参数,并返回一个 requests.Response 响应对象

类似的,还有 put,delete,head,post,option 请求函数

例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    query={'test1':'123456789','test2':'123456789'}
r=requests.get(url='https://www.baidu.com',params=query)
print r.url #返回URL地址
print r.status_code #返回状态码
print r.encoding #编码格式
print r.headers['Content-Type'] #获取网页header
print r.cookies #获取cookies
print r.text #Requests自动解码后数据
print r.content #获取二进制响应内容
print r.json() #JSON 响应内容 可以和 json 模块使用
输出:
https://www.baidu.com/?test1=123456789&test2=123456789
200
ISO-8859-1
text/html
<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
返回数据太多,这里不显示了

注意,get函数的params为查询字符串

例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   user_agent = 'Mozilla/5.0(X11; Linux x86_64) AppleWebKit/537.36(KHTML, like Gecko)Chrome/59.0.3071.115 Safari/537.36'
headers = {'User-Agent': user_agent}
data={'key1':'hello','key2':'world'}
r=requests.post(url='http://httpbin.org/post',headers=headers,data=data)
print r.text


输出:
{
"args": {},
"data": "",
"files": {},
"form": {
"key1": "hello",
"key2": "world"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Connection": "close",
"Content-Length": "21",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Mozilla/5.0(X11; Linux x86_64) AppleWebKit/537.36(KHTML, like Gecko)Chrome/59.0.3071.115 Safari/537.36"
}
...

这是一个 POST 请求 ,其中 data 参数表示要提交给服务器的数据 ,headers 是一个字典类型的请求头,此处我只指定了 User-Agent .

代理访问

为了访问一些被Q的网站,往往需要设置代理,幸运的是,requests同样也提供的代理这一功能,与之有关的参数为 proxies

例3

1
2
3
4
5
proxy={'http':'http://127.0.0.1:8087',
'https':'http://127.0.0.1:8087'}
r=requests.get(url='https://www.google.com',proxies=proxy,verify=False)
print r.text
print r.status_code

如果代理需要账户和密码, 则

1
2
3
proxies={
"http": "http://username:[email protected]:8087"
}

我把 verify 设置为 False,是为了SSL证书验证.

也可以通过环境变量 HTTP_PROXYHTTPS_PROXY 来配置代理

1
2
3
4
5
$ export HTTP_PROXY="http://10.10.1.10:3128"
$ export HTTPS_PROXY="http://10.10.1.10:1080"
$ python
>>> import requests
>>> requests.get("http://example.org")

会话(Session)

会话对象让你能够跨请求保持某些参数。它也会在同一个 Session 实例发出的所有请求之间保持 cookie, 期间使用 urllib3connection pooling 功能。所以如果你向同一主机发送多个请求,底层的 TCP 连接将会被重用,从而带来显著的性能提升。 (参见 HTTP persistent connection ).

使用之前需导入类: from requests import Session

准备的请求(Prepared Request)

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

例4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
user_agent = 'Mozilla/5.0(X11; Linux x86_64) AppleWebKit/537.36(KHTML, like Gecko)Chrome/59.0.3071.115 Safari/537.36'
headers={'User-Agent':user_agent}
# 开启回话
s= requests.Session()
req=requests.Request('GET',url='http://baidu.com')
# 开始准备一个请求
prepped= s.prepare_request(req)

# do something with prepped.body
# do something with prepped.headers
prepped.prepare_headers(headers)
# 发送以准备好的请求
resp= s.send(prepped,timeout=5)
print resp.status_code
s.close()

事件挂钩

Requests有一个钩子系统,你可以用来操控部分请求过程,或信号事件处理

可用的钩子:
response :
从一个请求产生的响应

可以通过传递一个 {hook_name: callback_function} 字典给 hooks 请求参数为每个请求分配一个钩子函数:

1
hooks=dict(response=print_url)

callback_function 会接受一个数据块作为它的第一个参数

1
2
def print_url(r, *args, **kwargs):
print(r.url)

例5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def print_urls(r,*args,**kwargs):
print r.url
pass
if __name__=='__main__':
s=requests.Session()
# 钩子
s.hooks=dict(response=print_urls)
req= requests.Request('GET',url='https://www.github.com',headers=header)

pre=s.prepare_request(req)
pre.prepare_headers(header)
resp=s.send(pre)
print resp.headers
pass

参考

http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

good~