优雅到骨子里的Requests

 
1528811134432
 

简介

 

上一篇文章介绍了Python的网络请求库urlliburllib3的使用方法,那么,作为同样是网络请求库的Requests,相对于urllib,有什么优点呢?

 

其实,只有两个词,简单优雅。

 

Requests的宣言就是:HTTP for Humans。可以说,Requests彻底贯彻了Python所代表的简单优雅的精神。

 

之前的urllib做为Python的标准库,因为历史原因,使用的方式可以说是非常的麻烦而复杂的,而且官方文档也十分的简陋,常常需要去查看源码。与之相反的是,Requests的使用方式非常的简单、直观、人性化,让程序员的精力完全从库的使用中解放出来。

 

甚至在官方的urllib.request的文档中,有这样一句话来推荐Requests

The Requests packageis recommended for a higher-level HTTP client interface.

 

Requests的官方文档同样也非常的完善详尽,而且少见的有中文官方文档:http://cn.python-requests.org/zh_CN/latest/。

 

当然,为了保证准确性,还是尽量查看英文文档为好。

 

作者

 

Requests的作者Kenneth Reitz同样是一个富有传奇色彩的人物。

 

Kenneth Reitz在有着“云服务鼻祖”之称的Heroku 公司,28岁时就担任了Python 语言的总架构师。他做了什么呢?随便列几个项目名称: requests、python-guide、pipenv、legit、autoenv,当然它也给Python界很多知名的开源项目贡献了代码,比如Flask。

 

可以说他是Python领域举足轻重的人物,他的代码追求一种强迫症般的美感。

 

大佬的传奇还不止于此,这是他当年在PyCON演讲时的照片:

 
1528811511456
 

非常可爱的小胖子,同时也符合着大众对于程序员的一些刻板印象:胖、不太修边幅、腼腆。

 

但是几年后,他变成了这样:

 
1528811688447
 

emmmmm,帅哥,你这是去哪整的容?

 

哈哈,开个玩笑。不过确实外貌方面的改变非常的巨大,由一个小肥宅的形象变得帅气潇洒。可见只要愿意去追求,我们都能变成我们想要的样子。

 

例子与特性

 

可以说Requests最大的特性就是其风格的简单直接优雅。无论是请求方法,还是响应结果的处理,还有cookies,url参数,post提交数据,都体现出了这种风格。

 

以下是一个简单例子:

  1. >>> import requests
  2. >>> resp = requests.get('https://www.baidu.com')
  3. >>> resp.status_code
  4. 200
  5. >>> resp.headers['content-type']
  6. 'application/json; charset=utf8'
  7. >>> resp.encoding
  8. 'utf-8'
  9. >>> resp.text
  10. u'{"type":"User"...'
 

可以看到,不论是请求的发起还是相应的处理,都是非常直观明了的。

 

Requests目前基本上完全满足web请求的所有需求,以下是Requests的特性:

  • Keep-Alive & 连接池

  • 国际化域名和 URL

  • 带持久 Cookie 的会话

  • 浏览器式的 SSL 认证

  • 自动内容解码

  • 基本/摘要式的身份认证

  • 优雅的 key/value Cookie

  • 自动解压

  • Unicode 响应体

  • HTTP(S) 代理支持

  • 文件分块上传

  • 流下载

  • 连接超时

  • 分块请求

  • 支持 .netrc

 

Requests 3.0目前也募集到了资金正在开发中,预计会支持async/await来实现并发请求,且可能会支持HTTP 2.0。

 

安装

 

Requests的安装非常的简单,直接PIP安装即可:

  1. pip install requests
 

使用

 

Requests的请求不再像urllib一样需要去构造各种Request、opener和handler,使用Requests构造的方法,并在其中传入需要的参数即可。

 

发起请求

 

请求方法

 

每一个请求方法都有一个对应的API,比如GET请求就可以使用get()方法:

  1. >>> import requests
  2. >>> resp = requests.get('https://www.baidu.com')
 

而POST请求就可以使用post()方法,并且将需要提交的数据传递给data参数即可:

  1. >>> import requests
  2. >>> resp = requests.post('http://httpbin.org/post', data = {'key':'value'})
 

而其他的请求类型,都有各自对应的方法:

  1. >>> resp = requests.put('http://httpbin.org/put', data = {'key':'value'})
  2. >>> resp = requests.delete('http://httpbin.org/delete')
  3. >>> resp = requests.head('http://httpbin.org/get')
  4. >>> resp = requests.options('http://httpbin.org/get')
 

非常的简单直观明了。


 

传递URL参数

 

传递URL参数也不用再像urllib中那样需要去拼接URL,而是简单的,构造一个字典,并在请求时将其传递给params参数:

  1. >>> import requests
  2. >>> params = {'key1': 'value1', 'key2': 'value2'}
  3. >>> resp = requests.get("http://httpbin.org/get", params=params)
 

此时,查看请求的URL,则可以看到URL已经构造正确了:

  1. >>> print(resp.url)
  2. http://httpbin.org/get?key2=value2&key1=value1
 

并且,有时候我们会遇到相同的url参数名,但有不同的值,而python的字典又不支持键的重名,那么我们可以把键的值用列表表示:

  1. >>> params = {'key1': 'value1', 'key2': ['value2', 'value3']}
  2. >>> resp = requests.get('http://httpbin.org/get', params=params)
  3. >>> print(resp.url)
  4. http://httpbin.org/get?key1=value1&key2=value2&key2=value3

 

自定义Headers

 

如果想自定义请求的Headers,同样的将字典数据传递给headers参数。

  1. >>> url = 'https://api.github.com/some/endpoint'
  2. >>> headers = {'user-agent': 'my-app/0.0.1'}
  3. >>> resp = requests.get(url, headers=headers)
 

自定义Cookies

 

Requests中自定义Cookies也不用再去构造CookieJar对象,直接将字典递给cookies参数。

  1. >>> url = 'http://httpbin.org/cookies'
  2. >>> cookies = {'cookies_are': 'working'}
  3. >>> resp = requests.get(url, cookies=cookies)
  4. >>> resp.text
  5. '{"cookies": {"cookies_are": "working"}}'
 

设置代理

 

当我们需要使用代理时,同样构造代理字典,传递给proxies参数。

  1. import requests
  2. proxies = {
  3. 'http': 'http://10.10.1.10:3128',
  4. 'https': 'http://10.10.1.10:1080',
  5. }
  6. requests.get('http://example.org', proxies=proxies)
 

重定向

 

在网络请求中,我们常常会遇到状态码是3开头的重定向问题,在Requests中是默认开启允许重定向的,即遇到重定向时,会自动继续访问。

  1. >>> resp = requests.get('http://github.com', allow_redirects=False)
  2. >>> resp.status_code
  3. 301
 

禁止证书验证

 

有时候我们使用了抓包工具,这个时候由于抓包工具提供的证书并不是由受信任的数字证书颁发机构颁发的,所以证书的验证会失败,所以我们就需要关闭证书验证。

 

在请求的时候把verify参数设置为False就可以关闭证书验证了。

  1. >>> import requests
  2. >>> resp = requests.get('http://httpbin.org/post', verify=False)
 

但是关闭验证后,会有一个比较烦人的warning

  1. py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  2. InsecureRequestWarning)
 

可以使用以下方法关闭警告:

  1. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  2. # 禁用安全请求警告
  3. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
 

设置超时

 

设置访问超时,设置timeout参数即可。

  1. >>> requests.get('http://github.com', timeout=0.001)
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
 

可见,通过Requests发起请求,只需要构造好几个需要的字典,并将其传入请求的方法中,即可完成基本的网络请求。

 

响应

 

通过Requests发起请求获取到的,是一个requests.models.Response对象。通过这个对象我们可以很方便的获取响应的内容。

 

响应内容卜卦

 

之前通过urllib获取的响应,读取的内容都是bytes的二进制格式,需要我们自己去将结果decode()一次转换成字符串数据。

 

Requests通过text属性,就可以获得字符串格式的响应内容。

  1. >>> import requests
  2. >>> resp = requests.get('https://api.github.com/events')
  3. >>> resp.text
  4. u'[{"repository":{"open_issues":0,"url":"https://github.com/...
 

Requests会自动的根据响应的报头来猜测网页的编码是什么,然后根据猜测的编码来解码网页内容,基本上大部分的网页都能够正确的被解码。而如果发现text解码不正确的时候,就需要我们自己手动的去指定解码的编码格式。

  1. >>> import requests
  2. >>> resp = requests.get('https://api.github.com/events')
  3. >>> resp.encoding = 'utf-8'
  4. >>> resp.text
  5. u'[{"repository":{"open_issues":0,"url":"https://github.com/...
 

而如果你需要获得原始的二进制数据,那么使用content属性即可。

  1. >>> resp.content
  2. b'[{"repository":{"open_issues":0,"url":"https://github.com/...
 

如果我们访问之后获得的数据是JSON格式的,那么我们可以使用json()方法,直接获取转换成字典格式的数据。

  1. >>> import requests
  2. >>> resp = requests.get('https://api.github.com/events')
  3. >>> resp.json()
  4. [{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...
 

状态码

 

通过status_code属性获取响应的状态码

  1. >>> resp = requests.get('http://httpbin.org/get')
  2. >>> resp.status_code
  3. 200
 

响应报头

 

通过headers属性获取响应的报头

  1. >>> r.headers
  2. {
  3. 'content-encoding': 'gzip',
  4. 'transfer-encoding': 'chunked',
  5. 'connection': 'close',
  6. 'server': 'nginx/1.0.4',
  7. 'x-runtime': '148ms',
  8. 'etag': '"e1ca502697e5c9317743dc078f67693f"',
  9. 'content-type': 'application/json'
  10. }
 

服务器返回的cookies

 

通过cookies属性获取服务器返回的cookies

  1. >>> url = 'http://example.com/some/cookie/setting/url'
  2. >>> resp = requests.get(url)
  3. >>> resp.cookies['example_cookie_name']
  4. 'example_cookie_value'
 

url

 

还可以使用url属性查看访问的url。

  1. >>> import requests
  2. >>> params = {'key1': 'value1', 'key2': 'value2'}
  3. >>> resp = requests.get("http://httpbin.org/get", params=params)
  4. >>> print(resp.url)
  5. http://httpbin.org/get?key2=value2&key1=value1
 

Session

 

Requests中,实现了Session(会话)功能,当我们使用Session时,能够像浏览器一样,在没有关闭关闭浏览器时,能够保持住访问的状态。

 

这个功能常常被我们用于登陆之后的数据获取,使我们不用再一次又一次的传递cookies。

  1. import requests
  2. session = requests.Session()
  3. session.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
  4. resp = session.get('http://httpbin.org/cookies')
  5. print(resp.text)
  6. # '{"cookies": {"sessioncookie": "123456789"}}'
 

首先我们需要去生成一个Session对象,然后用这个Session对象来发起访问,发起访问的方法与正常的请求是一摸一样的。

 

同时,需要注意的是,如果是我们在get()方法中传入headerscookies等数据,那么这些数据只在当前这一次请求中有效。如果你想要让一个headersSession的整个生命周期内都有效的话,需要用以下的方式来进行设置:

  1. # 设置整个headers
  2. session.headers = {
  3. 'user-agent': 'my-app/0.0.1'
  4. }
  5. # 增加一条headers
  6. session.headers.update({'x-test': 'true'})
 

后记:或许有人不认可代码的美学,认为代码写的丑没事,能跑起来就好。但是我始终认为,世间万物都应该是美好的,追求美好的脚步也不应该停止。

内容补充:

get 方法

返回有 5 个属性

异常处理

返回200 正确

对应的 HTTP 协议

json参数

headers 参数

files 参数

timeout 参数, 以秒为单位

proxies  参数 设置代理服务器

潭州课堂25班:Ph201805201 爬虫基础 第四课 Requests (课堂笔记)的更多相关文章

  1. 潭州课堂25班:Ph201805201 爬虫基础 第八课 selenium (课堂笔记)

    Selenium笔记(1)安装和简单使用 简介 Selenium是一个用于Web应用程序测试的工具. Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE(7, 8, ...

  2. 潭州课堂25班:Ph201805201 爬虫基础 第三课 urllib (课堂笔记)

    Python网络请求urllib和urllib3详解   urllib是Python中请求url连接的官方标准库,在Python2中主要为urllib和urllib2,在Python3中整合成了url ...

  3. 潭州课堂25班:Ph201805201 爬虫基础 第六课 选择器 (课堂笔记)

    HTML解析库BeautifulSoup4 BeautifulSoup 是一个可以从HTML或XML文件中提取数据的Python库,它的使用方式相对于正则来说更加的简单方便,常常能够节省我们大量的时间 ...

  4. 潭州课堂25班:Ph201805201 爬虫基础 第十三课 cookie (课堂笔记)

    # -*- coding: utf-8 -*- # 斌彬电脑 # @Time : 2018/9/15 0015 4:52 #cookie 是服务器发给浏览器的特殊信息 # 可以理解为一个临时通行证 # ...

  5. 潭州课堂25班:Ph201805201 爬虫基础 第十一课 点触验证码 (课堂笔记)

    打开 网易盾 http://dun.163.com/trial/picture-click  ——在线体验——图中点选 打码平台 ——超级鹰    http://www.chaojiying.com/ ...

  6. 潭州课堂25班:Ph201805201 爬虫基础 第十课 图像处理- 极验验证码 (课堂笔记)

    用 python 的  selenium  访问  https://www.huxiu.com/ 自动通过验证码 # -*- coding: utf-8 -*- # 斌彬电脑 # @Time : 20 ...

  7. 潭州课堂25班:Ph201805201 爬虫基础 第七课 Python与常见加密方式 (课堂笔记)

    打开图形界面  18版 Python与常见加密方式 前言 我们所说的加密方式,都是对二进制编码的格式进行加密的,对应到Python中,则是我们的Bytes. 所以当我们在Python中进行加密操作的时 ...

  8. 潭州课堂25班:Ph201805201 爬虫基础 第五课 (案例) 豆瓣分析 (课堂笔记)

    动态讲求 , 翻页参数: # -*- coding: utf-8 -*- # 斌彬电脑 # @Time : 2018/9/1 0001 3:44 import requests,json class ...

  9. 潭州课堂25班:Ph201805201 爬虫高级 第四课 sclapy 框架 crawispider类 (课堂笔记)

    以上内容以 spider 类 获取 start_urls 里面的网页 在这里平时只写一个,是个入口,之后 通过 xpath 生成 url,继续请求, crawispider 中 多了个  rules  ...

随机推荐

  1. C语言函数调用栈(三)

    6 调用栈实例分析 本节通过代码实例分析函数调用过程中栈帧的布局.形成和消亡. 6.1 栈帧的布局 示例代码如下: //StackReg.c #include <stdio.h> //获取 ...

  2. Ubuntu/Debian apt-get 404 Not Found Package Repository Errors,无法找到包的错误

    最简单最常用的方法是,使用如下命令更新到新的版本: sudo apt-get dist-upgrade 但是这个方法有时候不一定能起作用,那么可以使用以下直接替换的命令: sudo sed -i -e ...

  3. ruia笔记

    ruia笔记 loop = loop or asyncio.new_event_loop() get_event_loop()方法仅在同样的线程中生效,如果在一个新线程中,应该用new_event_l ...

  4. Java快速学习笔记01

    这一波快速学习主要是应付校招笔面试用,功利性质不可避免. 学习网址: http://www.runoob.com/java/java-tutorial.html 执行命令解析: 以上我们使用了两个命令 ...

  5. GBDT、XGBOOST、LightGBM调参数

    总的认识: LightGBM  > XGBOOST  > GBDT 都是调参数比较麻烦. GBDT分类的最佳调参数的讲解: Gradient Boosting Machine(GBM)调参 ...

  6. 分布式调用技术 RPC VS REST

    一 分布式调用大体上就分为两类,RPC式的,REST式的,两者的区别主要是就是: 1. RPC是面向动作的(方法调用) 2. REST是面向资源的(URL表示资源,HTTP动词表示动作) 从变现形式来 ...

  7. python魔法函数(二)之__getitem__、__len__、__iter__

    魔法函数会增强python类的类型,独立存在 __getitem class Company: def __init__(self, employees): self.employees = empl ...

  8. Storm的部署

    配置方案如下 node1 Nimbus zookeeper node2 Supervisor zookeeper node3 Supervisor zookeeper node4 Supervisor ...

  9. LeetCode(6):Z字形转换

    Medium! 题目描述: 将字符串 "PAYPALISHIRING" 以Z字形排列成给定的行数:(下面这样的形状) P A H N A P L S I I G Y I R 之后按 ...

  10. pytest一:pytest 框架介绍

    pytest 是 python 的一种单元测试框架,与python 自带的 unittest测试框架类似,但是比 unittest 框架使用起来更简洁,效率更高.根据pytest 的官方网站介绍,它具 ...