Python爬虫利器:Requests库的使用

Requests:让HTTP服务人类。 本文中的有些内容来自官方网站,也有一部分是我的理解,算是个笔记版本吧。

1、requests是什么

写了一些爬虫,从urllib库转到requests库,到目前为止,个人感觉requests库是最简单易用的HTTP库,以下这段话来自requests官网:

Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用。 警告:非专业使用其他 HTTP 库会导致危险的副作用,包括:安全缺陷症、冗余代码症、重新发明轮子症、啃文档症、抑郁、头疼、甚至死亡。

字里行间透露着requests库的自信,它确实做到了。

以下为Requests库的功能特性,完全满足今日web的需求:

  • Keep-Alive & 连接池
  • 国际化域名和 URL
  • 带持久 Cookie 的会话
  • 浏览器式的 SSL 认证
  • 自动内容解码
  • 基本/摘要式的身份认证
  • 优雅的 key/value Cookie
  • 自动解压
  • Unicode 响应体
  • HTTP(S) 代理支持
  • 文件分块上传
  • 流下载
  • 连接超时
  • 分块请求
  • 支持 .netrc

2、安装及更新

2.1 安装

最简单的安装方式是pip安装,只需执行以下一条指令:

pip install requests

也可以通过git使用源码安装,需要执行以下两条指令:

git clone git://github.com/kennethreitz/requests.git
python setup.py install

2.2 更新

使用pip进行更新:

pip install --upgrade requests

3、使用

3.1 发送请求

我们以http://httpbin.org/网站作为测试目标,该网站专门为HTTP客户端提高测试服务。

使用该库要在文件开始部分导入Requests模块:

import requests

HTTP的请求类型有POST,GET,PUT,DELETE,HEAD 以及 OPTIONS,其中POST和GET是最常使用的,用requests实现这几种请求代码如下:

r = requests.get('https://httpbin.org/get')
r = requests.put("http://httpbin.org/put")
r = requests.delete("http://httpbin.org/delete")
r = requests.head("http://httpbin.org/get")
r = requests.options("http://httpbin.org/get")

我们得到了一个名为rResponse对象,我们可以从这个对象中获取想要的信息,例如状态码(r.status_code)、文本内容(r.text)等。

3.2 传递URL参数

经常可以看到一些网址中有一个?, 后面还跟着几个参数,这种URL其实传递了某种数据,例如http://httpbin.org/get?key=val。Requests允许使用params 关键字参数,以一个字符串字典来提供这些参数。如果想传递key1=val1key2=val2httpbin.org/get,那么可以使用如下代码:

payload = {'key1': 'val1', 'key2': 'val2', 'key3': None}
r = requests.get("http://httpbin.org/get", params=payload)
print(r.url)

执行结果为:http://httpbin.org/get?key1=val1&key2=val2

注:字典中值为None的键不会被添加到URL的查询字符串中。

还可以将一个列表作为值传入:

payload = {'key1': 'val1', 'key2': ['val2', 'val3']}
r = requests.get("http://httpbin.org/get", params=payload)
print(r.url)

执行结果为:http://httpbin.org/get?key1=val1&key2=val2&key2=val3

3.3 响应内容

3.3.1 文本响应内容

在3.1中已经提到Response对象包含很多信息,其中r.text为服务器响应内容:

r = requests.get("http://httpbin.org/get")
print(r.text)

执行结果为:

{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.18.4"
  }, 
  "origin": "114.244.178.208", 
  "url": "http://httpbin.org/get"
}

Requests可以自动对大多数unicode字符集无缝解码。

请求发出后,Requests会基于HTTP头部对响应的编码做出有根据的推测。我们可以通过r.encoding得到编码,也可以使用r.encoding属性改变编码。

3.3.2 二进制响应内容

上面r.text获得的是响应内容的文本,我们也可以以字节的方式访问请求响应体,对于非文本请求r.content,Requests会自动解码gzipdeflate传输编码的响应内容。

3.3.3 JSON响应内容

Requests内置一个JSON解码器,使用方法如下:

r = requests.get("http://httpbin.org/get")
print(r.json())

如果JSON解码失败,r.json()会抛出一个异常。需要注意的是,成功调用r.json()并不意味着响应成功,因为某些服务器会在失败的响应中包含一个JSON对象,这种JSON会被解码返回。如果要判断请求是否成功,我们可以使用r.raise_for_status()或者检查r.status_code是否和预期相同。

3.3.4 原始响应内容

有时候我们可能需要获取服务器的原始套接字响应,那么我们应该使用r.raw,使用时要确保在初始请求中设置了stream=True

r = requests.get("http://httpbin.org/get", stream=True)
print(r.raw)
print(r.raw.read(10))

执行结果如下:

<urllib3.response.HTTPResponse object at 0x0000021D55814320>
b'{\n  "args"'

4、定制请求头

请求某些服务器时需要加上请求头,Requests的请求接口有一个名为headers的参数,只需传给它一个字典即可:

headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get("http://httpbin.org/get", headers=headers)

注意: 定制 header 的优先级低于某些特定的信息源,例如:

  • 如果在 .netrc 中设置了用户认证信息,使用 headers= 设置的授权就不会生效。而如果设置了 auth= 参数,.netrc 的设置就无效了。
  • 如果被重定向到别的主机,授权 header 就会被删除。
  • 代理授权 header 会被 URL 中提供的代理身份覆盖掉。
  • 在我们能判断内容长度的情况下,header 的 Content-Length 会被改写。

更进一步讲,Requests 不会基于定制 header 的具体情况改变自己的行为。只不过在最后的请求中,所有的 header 信息都会被传递进去。

注意: 所有的 header 值必须是 string、bytestring 或者 unicode。尽管传递 unicode header 也是允许的,但不建议这样做。

5、响应状态码

我们可以响应状态码得知此次请求的结果,一般200为请求成功, Requests还附带了一个内置的状态码查询对象requests.codes

r = requests.get('http://httpbin.org/get')
print(r.status_code)
print(r.status_code == requests.codes.ok)

执行结果为:

200
True

如果发送了一个错误请求(一个 4XX 客户端错误,或者 5XX 服务器错误响应),我们可以通过 Response.raise_for_status()来抛出异常:

r = requests.get('http://httpbin.org/status/404')
print(r.status_code)
r.raise_for_status()

执行结果为:

404
---------------------------------------------------------------------------
HTTPError                                 Traceback (most recent call last)
<ipython-input-19-351ffd673854> in <module>()
      1 r = requests.get('http://httpbin.org/status/404')
      2 print(r.status_code)
----> 3 r.raise_for_status()

E:\Anaconda3\lib\site-packages\requests\models.py in raise_for_status(self)
    933 
    934         if http_error_msg:
--> 935             raise HTTPError(http_error_msg, response=self)
    936 
    937     def close(self):

HTTPError: 404 Client Error: NOT FOUND for url: http://httpbin.org/status/404

6、响应头

不只请求会有请求头,响应也有响应头:

r = requests.get('http://httpbin.org/get')
print(r.headers)
print(r.headers['Connection'])
print(r.headers['connection'])
print(r.headers['conNecTion'])

执行结果:

{
    "Connection": "keep-alive", 
    "Server": "meinheld/0.6.1", 
    "Date": "Thu, 25 Jan 2018 13:47:59 GMT", 
    "Content-Type": "application/json", 
    "Access-Control-Allow-Origin": "*", 
    "Access-Control-Allow-Credentials": "true", 
    "X-Powered-By": "Flask", 
    "X-Processed-Time": "0.00102591514587", 
    "Content-Length": "268", 
    "Via": "1.1 vegur"
}
keep-alive
keep-alive
keep-alive

可以看出该服务器响应头为Python字典形式,但是这个字典比较特殊:它是仅为HTTP头部而生的,是大小写不敏感的。我们可以以任意大小写形式来访问响应头字段,由上面的例子也可以看出。

7、超时

requests在发送请求时可以附带一个timeout参数,如果服务器在timeout秒内没有应答,将会引发一个异常,更精确地说,是在timeout秒内没有从基础套接字上接收到任何字节的数据时。如果我们不使用这个参数,我们的程序可能会永远失去响应。

r = requests.get('http://httpbin.org/get', timeout=0.01)

这样就可以得到一个超时异常:

timeout  Traceback (most recent call last)
ConnectTimeout: HTTPConnectionPool(host='httpbin.org', port=80): Max retries exceeded with url: /get (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000002BADB2A40F0>, 'Connection to httpbin.org timed out. (connect timeout=0.01)'))

8、错误与异常

遇到网络问题(如:DNS 查询失败、拒绝连接等)时,Requests 会抛出一个ConnectionError 异常。

如果 HTTP 请求返回了不成功的状态码, Response.raise_for_status() 会抛出一个 HTTPError 异常。

若请求超时,则抛出一个 Timeout 异常。

若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects 异常。

所有Requests显式抛出的异常都继承自 requests.exceptions.RequestException

9、 代理

某些网站对同一IP的访问频率和次数做了限制,如果想要突破这些限制,频繁替换代理是一种最简单的解决办法。Requests库也为我们提供了代理的使用,只要在发送请求时指定proxies参数即可:

proxies = {
  "http": "http://10.111.1.14:1212",
  "https": "http://10.110.1.10:1213",
}

r = requests.get("http://httpbin.org/get", proxies=proxies)

如果使用的代理需要使用HTTP Basic Auth,可以使用http://user:password@host/语法:

proxies = {
    "http": "http://user:pass@10.10.1.10:3128/",
}

如果要为某个特定主机设置代理,使用scheme://hostname作为key,它会为指定的主机进行匹配代理:

proxies = {'http://10.20.1.128': 'http://10.10.1.10:5323'}

至此,Requests库的常用功能介绍完毕,如果想要进阶功能的使用教程,请移步官方网站:

Requests高级用法

原文发布于微信公众号 - C与Python实战(CPythonPractice)

原文发表时间:2018-01-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Django Scrapy

day4 hadoop

最新日志查看 ls -lrt 监控系统命令 top vmstat * ( *输入数字 前边是多少秒一次 后边是次数) Oracle创建用户等一系列 cr...

2824
来自专栏我的博客

PHP敏感函数关闭参考

搜索disable_functions 然后改为=disable_functions=phpinfo,dl, exec, system,passthru,pop...

3858
来自专栏Python

python并发编程之多进程理论部分

一 并发与并行   无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真是干活的是cpu,cpu来做这些任务,而一个cp...

2195
来自专栏前端菜鸟变老鸟

sublime VI编辑器 十分钟熟练掌握各种命令

大家都知道,写代码的时候总有许多繁琐的操作,换行、删除一行、复制一行、去到行首、行尾等等。通常情况下是使用鼠标直接点击,这会大大的降低我们的开发效率,因此大家想...

881
来自专栏wblearn

redis应用的总结

对最近项目应用redis做一个简单总结,项目中的营业网点资料和客户资料等模块以后的资料量势必会随着业务的扩张会越来越大,可能会造成系统性能瓶颈及用户体验不佳等,...

851
来自专栏Flutter入门到实战

一行代码快速解耦Application逻辑,让Application更简洁好维护

版权声明:本文为博主原创文章,未经博主允许不得转载。https://www.jianshu.com/p/23b9ba9b685d

883
来自专栏架构说

河狸家:Redis 源码的深度剖析

大家好!我叫陈科,目前就职于河狸家,主要做架构方面的工作,今天和大家分享的是 Redis 的源码分析。 Redis 这个东西很简单,懂 C 语言的同学花一个下...

3617
来自专栏PHP在线

PHP转义Json里的特殊字符的函数

在给一个 App 做 API,从服务器端的 MySQL 取出数据,然后生成 JSON。数据中有个字段叫 content,里面保存了文章内容,含有大量 HTML ...

3996
来自专栏PHP技术大全

通过代码审计找出网站中的XSS漏洞实战(三)

笔者此前录制了一套XSS的视频教程,在漏洞案例一节中讲解手工挖掘、工具挖掘、代码审计三部分内容,准备将内容用文章的形式再次写一此,前两篇已经写完,内容有一些关联...

1552
来自专栏极客猴

详解 python3 urllib

本文是爬虫系列文章的第一篇,主要讲解 Python 3 中的 urllib 库的用法。urllib 是 Python 标准库中用于网络请求的库。该库有四个模块,...

1111

扫码关注云+社区

领取腾讯云代金券