肉渣教程

网络请求requests库

上一节 下一节

Python内置的urllib2模块也可以发送网络请求,但是更加推荐的是第三方库requests库,该库用起来更舒服、更人性。


安装requests库

使用pip即可安装requests库;sudo代表是使用管理员权限来进行安装。

$ sudo pip install requests

发送get请求

使用requests库发送网络请求非常简单。导入requests模块后,requests.get方法请求指定url地址即可。如下所示,先导入requests模块:

>>> import requests

再使用get方法请求指定url地址,这里以请求GitHub公共时间线为例:

>>> r = requests.get( "https://sand-box.cn/action_page" )

请求结束,得到名为r的Response对象,从对象r中即可获得想要的信息:

>>> r
<Response [200]>
>>> r.text
u'\u6536\u5230\u8868\u5355\u6570\u636e\u5982\u4e0b\u6240\u793a\uff1a<br>{}'

r.text的值就是get请求返回的内容;Response[200]是代表请求成功,其中200是代表请求成功的响应状态码。

传递url参数

如下所示,使用params形参,传入一个字典来提供url参数。

>>> import requests
>>> url = "https://sand-box.cn/action_page"
>>> args = {'k1': 'v1', 'k2': 'v2'}
>>> r = requests.get( url, params=args )

>>> print r.url
https://sand-box.cn/action_page?k2=v2&k1=v1
>>> print r.text
收到表单数据如下所示:<br>{"k2": "v2", "k1": "v1"}

发送post请求

post请求中,若要发送表单数据,则应以字典形式的数据传参给data参数,如下:

>>> import requests
>>> url = "https://sand-box.cn/action_page"
>>> data = {'k1': 'v1', 'k2': 'v2'}

>>> r = requests.post( url, data=data )
>>> print r.text
收到表单数据如下所示:<br>{"k2": "v2", "k1": "v1"}

发送JSON格式字符串

除了使用dict的形式发送表单数据,其实还可以直接发送字符串,比如发送JSON格式字符串。

>>> import json

>>> url = '换上接受JSON的url地址'
>>> data = {'zhuan': 'fou'}
>>> data = json.dumps( data )

>>> r = requests.post(url, data=data)


requests还提供了另外一种实现方式,即将字典内容直接传入形参json,然后字典就会自动转成json格式,如下:

>>> url = '换上接受JSON的url地址'
>>> data = {'zhuan': 'fou'}

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

响应对象

上述各示例中的变量r,存储的是每次请求的响应对象。

>>> import requests
>>> r = requests.get( "https://sand-box.cn/action_page" )
>>> r.text  # 返回响应内容
u'\u6536\u5230\u8868\u5355\u6570\u636e\u5982\u4e0b\u6240\u793a\uff1a<br>{}'

>>> r.content  # 以字节的方式返回响应内容(对二进制响应内容更有意义)
'\xe6\x94\xb6\xe5\x88\xb0\xe8\xa1\xa8\xe5\x8d\x95\xe6\x95\xb0\xe6\x8d\xae\xe5\xa6\x82\xe4\xb8\x8b\xe6\x89\x80\xe7\xa4\xba\xef\xbc\x9a<br>{}'

>>> r.encoding  # 响应内容的编码格式
'UTF-8'

>>> r.url  # 响应的url地址
u'https://sand-box.cn/action_page'

>>> r.status_code  # 返回响应状态码
200

>>> r.headers  # 返回响应头(dict类型)
{'content-encoding': 'gzip', 'transfer-encoding': 'chunked', 'vary': 'Accept-Encoding', 'server': 'TornadoServer/5.0.2', 'connection': 'keep-alive', 'etag': 'W/"40ea2ab22f2265a5daf7e82f6cece8635e730579"', 'date': 'Mon, 04 Mar 2019 03:06:06 GMT', 'content-type': 'text/html; charset=UTF-8'}

二进制响应内容

上文已经说了使用content属性可以字节的方式访问响应对象,比如请求的是一张网络图片,就可以根据content属性的值在本地创建此图像文件。(需要安装PiL库,也就是Pillow库,专门用于图像处理的。)

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

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

JSON响应内容

Requests库中内置了JSON解码器,若响应内容是JSON格式字符串,直接调用响应对象的内置函数json即可返回dict类型对象。

>>> import requests

>>> r = requests.get('https://api.github.com/events')
>>> r.json()
[{u'payload': {u'size': 1, u'head': u'd000b6f...

定制请求头

如果想订制HTTP请求的头部,就将想定义的内容以字典的形式传到形参header,示例如下:

>>> url = 'https://sand-box.cn/action_page'
>>> headers = {'user-agent': 'example'}

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

Cookie

如果某个响应中包含了某些cookie,可如下快速访问cookie内容:

>>> url = '请换上响应中带有cookie的url地址'
>>> r = requests.get(url)

>>> r.cookies['cookie_name']
'cookie_value'


若发送请求时想带上cookies,可使用cookies参数如下:

>>> url = 'http://httpbin.org/cookies'
>>> cookies = { "zhuan": "fou" }

>>> r = requests.get(url, cookies=cookies)
>>> print r.text
{
  "cookies": {
    "zhuan": "fou"
  }
}

重定向与请求历史

默认情况下,get请求和post请求都会自动处理所有的重定向。如下所示,变量r的history属性是用来追踪重定向的响应历史,返回由老至新的响应对象构成的列表。

示例如下,GitHub会将所有的HTTP请求重定向到HTTPS:

>>> r = requests.get( 'http://github.com' )

>>> r.url
u'https://github.com/'

>>> r.status_code
200

>>> r.history
[<Response [301]>]


若想禁止自动重定向,那就要手动将形参allow_redirects设置成False才行。

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

>>> r.status_code
301

>>> r.history
[]

超时

设置形参timeout,单位为秒;即请求若超过timeout参数设定的秒数,则停止等待响应。

>>> requests.get('https://github.com', timeout=0.001)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
requests.exceptions.Timeout: (<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x105497990>, 'Connection to github.com timed out. (connect timeout=0.001)')

不过需要注意的是timeout仅对连接过程有效,与Response的下载无关。换言之,只要请求在timeout限制范围内得到服务器的响应即可,Response就算五百年没下载完毕也不会触发超时。


Requests库非常强大,足以应付大多请求场景;如果是比较简单的AJAX接口,也可以使用requests库解决;对于更加复杂的场景,也许会用到python的selenium库。最后要说的,python在爬虫领域非常强大,但是开发者一定要恪守两点,法律与道德。破坏计算机信息系统罪是刑事犯罪;即使有些事情是法律的边缘,也应再三自我拷问是否道德。


网络请求requests库

上一节 下一节