Python内置的urllib2模块也可以发送网络请求,但是更加推荐的是第三方库requests库,该库用起来更舒服、更人性。
使用pip即可安装requests库;sudo代表是使用管理员权限来进行安装。
$ sudo pip install requests
使用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是代表请求成功的响应状态码。
如下所示,使用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请求中,若要发送表单数据,则应以字典形式的数据传参给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"}
除了使用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) )
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内容:
>>> 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在爬虫领域非常强大,但是开发者一定要恪守两点,法律与道德。破坏计算机信息系统罪是刑事犯罪;即使有些事情是法律的边缘,也应再三自我拷问是否道德。