在系列文章的第一篇中介绍了 HTTP 协议,Python 提供了不少模块来基于 HTTP 协议的网络编程,urllib、urllib二、urllib三、httplib、httplib2,都是和 HTTP 相关的模块,看名字以为很反人类,更糟糕的是这些模块在 Python2 与 Python3 中有很大的差别,若是业务代码要同时兼容 2 和 3,写起来会让人崩溃。javascript

幸运地是,繁荣的 Python 社区给开发者带来了一个很是惊艳的 HTTP 库 requests,一个真正给人用的HTTP库。它是 GitHUb 关注数最多的 Python 项目之一,requests 的做者是 Kenneth Reitz 大神。html

requests 实现了 HTTP 协议中绝大部分功能,它提供的功能包括 Keep-Alive、链接池、Cookie持久化、内容自动解压、HTTP代理、SSL认证、链接超时、Session等不少特性,最重要的是它同时兼容 python2 和 python3。java

快速入门

requests 的安装能够直接使用 pip 方法:pip install requestspython

>>> import requests # GET 请求 >>> response = requests.get("https://foofish.net")

返回的时 Response 对象,Response 对象是 对 HTTP 协议中服务端返回给浏览器的响应数据的封装,响应的中的主要元素包括:状态码、缘由短语、响应首部、响应体等等,这些属性都封装在Response 对象中。nginx

# 状态码 >>> response.status_code 200 # 缘由短语 >>> response.reason 'OK' # 响应首部 >>> for name,value in response.headers.items(): ... print("%s:%s" % (name, value)) ... Content-Encoding:gzip Server:nginx/1.10.2 Date:Thu, 06 Apr 2017 16:28:01 GMT # 响应内容 >>> response.content '<html><body>此处省略一万字...</body></html>

requests 除了支持 GET 请求外,还支持 HTTP 规范中的其它全部方法,包括 POST、PUT、DELTET、HEADT、OPTIONS方法。编程

>>> r = requests.post('http://httpbin.org/post', data = {'key':'value'}) >>> r = requests.put('http://httpbin.org/put', data = {'key':'value'}) >>> r = requests.delete('http://httpbin.org/delete') >>> r = requests.head('http://httpbin.org/get') >>> r = requests.options('http://httpbin.org/get')

构建请求查询参数

不少URL都带有很长一串参数,咱们称这些参数为URL的查询参数,用"?"附加在URL连接后面,多个参数之间用"&"隔开,好比:http://fav.foofish.net/?p=4&s=20 ,如今你能够用字典来构建查询参数:json

>>> args = {"p": 4, "s": 20} >>> response = requests.get("http://fav.foofish.net", params = args) >>> response.url 'http://fav.foofish.net/?p=4&s=2'

构建请求首部 Headers

requests 能够很简单地指定请求首部字段 Headers,好比有时要指定 User-Agent 假装成浏览器发送请求,以此来蒙骗服务器。直接传递一个字典对象给参数 headers 便可。api

>>> r = requests.get(url, headers={'user-agent': 'Mozilla/5.0'})

构建 POST 请求数据

requests 能够很是灵活地构建 POST 请求须要的数据,若是服务器要求发送的数据是表单数据,则能够指定关键字参数 data,若是要求传递 json 格式字符串参数,则可使用json关键字参数,参数的值均可以字典的形式传过去。浏览器

做为表单数据传输给服务器服务器

>>> payload = {'key1': 'value1', 'key2': 'value2'} >>> r = requests.post("http://httpbin.org/post", data=payload)

做为 json 格式的字符串格式传输给服务器

>>> import json >>> url = 'http://httpbin.org/post' >>> payload = {'some': 'data'} >>> r = requests.post(url, json=payload)

Response中的响应体

HTTP返回的响应消息中很重要的一部份内容是响应体,响应体在 requests 中处理很是灵活,与响应体相关的属性有:content、text、json()。

content 是 byte 类型,适合直接将内容保存到文件系统或者传输到网络中

>>> r = requests.get("https://pic1.zhimg.com/v2-2e92ebadb4a967829dcd7d05908ccab0_b.jpg")
>>> type(r.content)
<class 'bytes'>
# 另存为 test.jpg
>>> with open("test.jpg", "wb") as f:
...     f.write(r.content)

text 是 str 类型,好比一个普通的 HTML 页面,须要对文本进一步分析时,使用 text。

>>> r = requests.get("https://foofish.net/understand-http.html")
>>> type(r.text)
<class 'str'>
>>> re.compile('xxx').findall(r.text)

若是使用第三方开放平台或者API接口爬取数据时,返回的内容是json格式的数据时,那么能够直接使用json()方法返回一个通过json.loads()处理后的对象。

>>> r = requests.get('https://www.v2ex.com/api/topics/hot.json') >>> r.json() [{'id': 352833, 'title': '在长沙,父母同住...

代理设置

当爬虫频繁地对服务器进行抓取内容时,很容易被服务器屏蔽掉,所以要想继续顺利的进行爬取数据,使用代理是明智的选择。若是你想爬取墙外的数据,一样设置代理能够解决问题,requests 完美支持代理。

import requests proxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080', } requests.get('http://example.org', proxies=proxies)

超时设置

requests 发送请求时,默认请求下线程一直阻塞,直到有响应返回才处理后面的逻辑。若是遇到服务器没有响应的状况时,问题就变得很严重了,它将致使整个应用程序一直处于阻塞状态而无法处理其余请求。

>>> import requests >>> r = requests.get("http://www.google.coma") ...一直阻塞中

正确的方式的是给每一个请求显示地指定一个超时时间。

>>> r = requests.get("http://www.google.coma", timeout=5) 5秒后报错 Traceback (most recent call last): socket.timeout: timed out

Session

爬虫入门系列(一):快速理解HTTP协议中介绍过HTTP协议是一中无状态的协议,为了维持客户端与服务器之间的通讯状态,使用 Cookie 技术使之保持双方的通讯状态。

有些网页是须要登陆才能进行爬虫操做的,而登陆的原理就是浏览器首次经过用户名密码登陆以后,服务器给客户端发送一个随机的Cookie,下次浏览器请求其它页面时,就把刚才的 cookie 随着请求一块儿发送给服务器,这样服务器就知道该用户已是登陆用户。

import requests # 构建会话 session = requests.Session() # 登陆url session.post(login_url, data={username, password}) # 登陆后才能访问的url r = session.get(home_url) session.close()

构建一个session会话以后,客户端第一次发起请求登陆帐户,服务器自动把cookie信息保存在session对象中,发起第二次请求时requests 自动把session中的cookie信息发送给服务器,使之保持通讯状态。

项目实战

最后是一个实战项目,如何用 requests 实现知乎自动登陆并给用户发私信,我会在下一篇文章中进行讲解,关注公众号 ‘Python之禅’。

延伸阅读:

同步发表博客:https://foofish.net/http-requests.html公众号:Python之禅 (id:VTtalk),分享 Python 等技术干货