——爬虫第一步是发起请求。Python有内置的HTTP请求库Urllib,但是Urllib使用起来比较不方便。而Requests是python最简单易用的HTTP库,做爬虫建议使用Requests库。
官方文档:http://2.python-requests.org/zh_CN/latest/index.html
Requests库是第三方库,需要通过pip安装
pip install requests
Requests功能详解:
-
Requests基本演示
import requests
r = requests.get('http://www.baidu.com')
print(type(r))
print(r.status_code)
print(r.headers)
print(r.encoding)
print(r.text[:500])
print(type(r.text))
运行结果:
<class 'requests.models.Response'>
200
{'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Tue, 16 Jul 2019 10:25:12 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:27:43 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Transfer-Encoding': 'chunked'}
ISO-8859-1
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>ç�¾åº¦ä¸�ä¸�ï¼�ä½ å°±ç�¥é��</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www
<class 'str'>
在上面代码中,我们用requests的get()
方法去请求百度网页
type(r)
返回<class 'requests.models.Response'>
,表示它是一个类,这个类是Response对象
,用.text
属性可以响应字符串形式
r.status_code
返回状态码200,表示请求成功
r.headers
用来获得头部信息
r.encoding
是Requests 基于 HTTP 头部推测出来的响应编码方式,也是Requests默认的响应编码方式,我们看到它返回居然这样一个编码ISO-8859-1
,这样的编码并不能解析中文,所以我们可以看到r.text
返回的页面内容<title>ç�¾åº¦ä¸�ä¸�ï¼�ä½ å°±ç�¥é��</title>
这个title标签的内容乱码
仔细看r.text
返回的页面内容,我们可以看到一个字段charset=utf-8
,这说明百度网页的编码应该就是'utf-8'了,我们可以用Response对象
的apparent_encoding
属性来打印它的编码。这个apparent_encoding
属性可以从响应内容中来分析出编码
如下代码:
import requests
r = requests.get('http://www.baidu.com')
print(r.apparent_encoding)
运行结果:
utf-8
可以这么认为,如果headers中不存在charset
字段,则默认编码为ISO-8859-1
,这也就是r.encoding
返回ISO-8859-1
的原因
下面,将编码ISO-8859-1
替换成'utf-8'
:
import requests
r = requests.get('http://www.baidu.com')
r.encoding = 'utf-8'
print(r.text[:500])
运行结果:
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_
可以看到,<title>百度一下,你就知道</title>
没有乱码了
事实上,我们知道用apparent_encoding
属性可以分析出响应内容的编码,那么我们直接用它来自动转编码可以了,不用去管它是什么编码
import requests
r = requests.get('http://www.baidu.com')
r.encoding = r.apparent_encoding
print(r.text[:500])
-
Response对象的常用属性
r.status_code # HTTP请求的返回状态,200表示连接成功,404表示失败
r.encoding # 从HTTP headers中猜测的响应内容编码方式
r.apparent_encoding # 从内容中分析出的响应内容编码方式
r.text # HTTP响应内容的字符串形式,即,url对应的页面内容
r.content # HTTP响应内容的二进制形式
-
Response对象的处理方式
r.text
r.content
r.json()
我们请求url
得到Response对象,需要根据响应内容信息进行处理
r.text
返回文本,这要求我们的url
对应一个html
网页
r.content
返回字节,这要求我们的url
对应图像或影音的链接
r.json()
是Requests内置的Json解码器的方法,可以处理Json数据,返回字典dict
,这要求我们的url
对应的响应体是Json对象
——当我们用r.text
得到html页面时,需要提取其中的数据,可用正则表达式匹配提取,或交给页面解析库处理,如:BeautifulSoup、XPath
以上,就是Requests库解析数据的处理方法
-
Requests库的常用方法
get()是Requests最常用的方法,获得一个网页最简单的一行代码就是:
r = requests.get(url)
上面我们已经演示过了,而get()方法完整的语法如下:
requests.get(url,params = None,**kwarge)
url
:获取页面的链接
paiams
:url中的额外参数,字典或字节流格式,可选
**kwarge
:12个控制访问的参数
我们打开Requests库get()
方法的源代码,可以发现其实get()
方法是用requests()
方法来封装的,如下图:

在这个源代码中,可以看到Requests库提供了7个方法,这7个方法都是通过调用一个基础方法requests()
方法来实现的,可以这么说,Requests库其实只有一个方法,那就是requests()
方法,但是为了让大家编写程序方便,又提供了额外的方法
我们可以看到,get()是用如下的方法来封装的
requests('get',url,params = params,**kwarge)
下面,是这个源代码中Requests库的7个方法的完整语法:
import requests
requests.get(url, params=None, **kwargs)
requests.head(url, **kwargs)
requests.post(url, data=None, json=None, **kwargs)
requests.put(url, data=None, **kwargs)
requests.patch(url, data=None, **kwargs)
requests.delete(url, **kwargs)
requests.options(url, **kwargs)
还有一个基础方法requests()
方法:
import requests
request(method, url, **kwargs)
在这个基础方法中,method
是请求方式,也就是7个方法,**kwargs
是13个控制访问参数
下面,介绍Request库的常用方法
Request库的方法介绍
方法 |
说明 |
---|---|
requests.request() |
构造一个请求,支撑一下各方法的基础方法 |
requests.get() |
获取HTML网页的主要方法,对应于HTTP的GET |
requests.head() |
获取HTML网页头信息的方法,对应于HTTP的HEAD |
requests.post() |
向HTML网页提交POST请求的方法,对应于HTTP的POST |
requests.put() |
向HTML网页提交PUT请求的方法,对应于HTTP的PUT |
requests.patch() |
向HTML网页提交局部修改请求,对应于HTTP的PATCH |
requests.delete() |
向HTML页面提交删除请求,对应于HTTP的DELETE |
我们发现,Requests库的方法与HTTP协议的方法在功能上是一一对应的,所以我们需要了解HTTP协议才能更好理解Requests库的方法:
HTTP协议是什么?
HTTP,Hypertext Transfer Protocol,超文本传输协议。
HTTP是一个基于"请求与响应"模式的、无状态的应用层协议。
HTTP协议采用URL作为定位网络资源的标识。
URL格式 http:// host [:port] [path]
host:合法的Internet主机域名或IP地址
port:端口号,缺省端口为80
path:请求资源的路径
—— url 就像我们电脑上一个文件或目录的路径,只不过这个路径是Internet上面的,每一个url对应一个数据资源
HTTP协议对资源的操作
方法 |
说明 |
---|---|
GET |
请求获取URL位置的资源 |
HEAD |
请求获取URL位置资源的响应消息报告,即获得该资源的头部信息 |
POST |
请求向URL位置的资源后附加新的数据 |
PUT |
请求向URL位置存储的一个资源,覆盖原URL位置的资源 |
PATCH |
请求局部更新URL位置的资源,即改变该处资源的部分内容 |
DELETE |
请求删除URL位置存储的资源 |
我们可以把互联网或Internet当成一个云端,url就是云端中资源的路径
如果我们想获取url上的资源,可以用GET、HEAD
如果我们想上传资源到url上,可以用POST、PUT、PATCH
如果我们想删除url上的资源,可以用DELETE

再说options请求:
那么什么是options请求呢?
我们把上面6个请求做下分类:
简单请求(simple request) |
非简单请求(not-simple request) |
---|---|
GET、HEAD、POST |
PUT、PATCH、DELETE |
出于安全考虑,并不是所有域名访问后端服务都可以。其实在正式跨域之前,浏览器会根据需要发起一次预检(也就是options请求),用来让服务端返回允许的方法(如get、post),被跨域访问的Origin(来源或者域),还有是否需要Credentials(认证信息)等。
对于简单请求浏览器不会预检,而非简单请求会预检
13个控制访问的参数
上面说了,基础方法request(method, url, **kwargs)
有13个控制访问的参数,可选的(可选参数在写法上要用赋值号 =
),其它6个常用方法的参数其实也一样
1. params : 字典或字节序列,作为参数增加到url中
2. data : 字典、字节序列或文件对象,作为Request的内容
3. json : JSON格式的数据,作为Request的内容
4. headers : 字典,HTTP定制头
5. cookies : 字典或CookieJar,Request中的auth : 元组支持HTTP认证功能
6. files : 字典类型,传输文件
7. timeout : 设定超时时间,秒为单位
8. proxies : 字典类型,设定访问代理服务器,可以增加登录认证
9. allow_redirects : True/False,默认为True,重定向开关
10. stream : True/False,默认为True,获取内容立即下载开关
11. verify : True/False,默认为True,认证SSL证书开关
12. cert : 本地SSL证书
13. auth : 元组,支持HTTP认证功能
Requests库常用方法的基本语法:
import requests
r = requests.get('http://httpbin.org/get')
r = requests.head('http://httpbin.org/head')
r = requests.post('http://httpbin.org/post', data = {'key':'value'})
r = requests.put('http://httpbin.org/put', data = {'key':'value'})
r = requests.patch('http://httpbin.org/pacth', data = {'key':'value'})
r = requests.delete('http://httpbin.org/delete')
Requests库常用方法实例展示
- head()方法仅用于取出头部信息的,如下代码:
import requests
r = requests.head('http://www.baidu.com')
print(r.text)
运行结果:
>>>
运行结果为空,表示head()方法不能用于展示html页面信息,我们只能用r.headers
取出头部信息,这说明head()方法可以用很小的流量来获取网络资源的概要。
- post()方法用于向服务器提交新增数据
如下代码,我们先建一个字典payload,然后用post()方法提交这个字典
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data = payload)
print(r.text)
运行结果:
{
"args": {},
"data": "",
"files": {},
"form": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "23",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"origin": "119.129.131.106, 119.129.131.106",
"url": "https://httpbin.org/post"
}
我们看到,'key1': 'value1', 'key2': 'value2'
被放到form字段下,这说明我们用post()方法提交字典
或键值对
时,会默认存储到表单的字段下。
假如,我们不提交键值对,提交字符串会怎么呢?
import requests
r = requests.post("http://httpbin.org/post", data = "ABC")
print(r.text)
运行结果:
{
"args": {},
"data": "ABC",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "3",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"origin": "119.129.131.106, 119.129.131.106",
"url": "https://httpbin.org/post"
}
字符串"ABC"被放到data字段下
这说明post()方法会根据用户提交信息的不同做相应的处理
—小结—:
上面讲了,Requests库提供了7个对外的常用方法,而实际上由于网络安全的限制,我们很难向URL去发起put()、patch()、delete()的请求,所以我们爬虫常用的就是get()、post()的方法了
>>>
阅读更多文章请点击以下链接:
python爬虫从入门到放弃之一:认识爬虫
python爬虫从入门到放弃之二:HTML基础
python爬虫从入门到放弃之三:爬虫的基本流程
python爬虫从入门到放弃之四:Requests库基础
python爬虫从入门到放弃之五:Requests库高级用法
python爬虫从入门到放弃之六:BeautifulSoup库
python爬虫从入门到放弃之七:正则表达式
python爬虫从入门到放弃之八:Xpath
python爬虫从入门到放弃之九:Json解析
python爬虫从入门到放弃之十:selenium库
python爬虫从入门到放弃之十一:定时发送邮件
python爬虫从入门到放弃之十二:多协程
python爬虫从入门到放弃之十三:Scrapy概念和流程
python爬虫从入门到放弃之十四:Scrapy入门使用
网友评论