前言
本文详细介绍了requests模块的安装及使用,从零开始带领大家学会如何利用python构建爬虫程序,内容丰富,包含了requests模块的各种功能;通过案例讲解使大家可以更好的理解与使用
1、Request请求库的介绍与安装
1.1 作用
发送网络请求,获得响应数据
官方文档:
https://requests.readthedocs.io/zh_CN/latest/index.html
1.2 介绍
Requests是用python语言基于urlib编写的,采用的是Apache2 Licensed开源协议的HTTP库,它比urllib更加方便,可以节约大量的工作,完全满足HTTP测试需求的库
一句话——Requests是一个Python代码编写的HTTP请求库,方便在代码中模拟浏览器发送http请求
1.3 安装
安装命令:
pip insatll requests
打开电脑cmd命令窗口,直接输入命令回车即可:
2、Request请求
2.1 request模块的用法
2.1.1 导入 requests模块
语法格式:
import requests
2.1.2 发送请求,生成响应体对象
语法格式:
响应对象=requests.get(目标URL)
案例:
import requests # 导入模块
# 发送请求,目标URL:https://www.baidu.com/
response = requests.get('https://www.baidu.com/') # reponse作为响应体对象
# 响应体对象中包含了:响应源码内容、响应状态码、响应URL
2.1.3 查看响应源码内容
语法格式:
响应对象.text
因为没有携带身份信息,这里得到的响应内容可能是假的,后面会学到,不用着急
2.1.4 查看响应状态码
语法格式:
响应对象.status_code
2.1.5 查看响应URL
语法格式:
响应对象.url
案例总结:
import requests # 导入模块
# 1、发送请求,目标URL:https://www.baidu.com/
response = requests.get('https://www.baidu.com/') # reponse作为响应体对象
# 响应体对象中包含了:响应源码、响应状态码、响应URL
# 2、查看响应体内容
print(response.text)
# 查看响应内容的数据类型
print(type(response.text)) # 字符串型
# 3、查看响应源码
print(response.status_code)
# 4、查看响应URL
print(response.url)
2.2 请求方式
我们主要使用get
请求和post
请求:
如:
-
get请求
requests.get(‘http://httpbin.org/get’) -
post请求
requests.post(‘http://httpbin.org/post’) -
其它请求
requests.put(‘http://httpbin.org/put’)
requests.delete(‘http://httpbin.org/delete’)
requests.head(‘http://httpbin.org/head’)
requests.options(‘http://httpbin.org/options’)
2.3 带参数的get请求
1、目标网站
url = ‘http://httpbin.org/get’
2、发送请求
方法1:将参数写在url后面
import requests
url = 'http://httpbin.org/get?name=lisi&age=10' # ?后是参数
reponse = requests.get(url)
方法2:将参数单独构建在字典中(推荐)
import requests
# 参数构建到字典中
pam = {
'name':'lsis',
'age':10
}
url = 'http://httpbin.org/get'
reponse = requests.get(url,params=pam)
# params:用来携带get请求的参数,将参数传入请求
2.4 带参数的post请求
import requests
# 目标网站
url = 'http://httpbin.org/post'
# 将参数构建到字典当中
data = {
'lisi':10
}
reponse = requests.get(url,data=data)
# data:用来携带post请求的参数
说明:
1、post请求的参数不能写在url后面,只能通过字典传参
2、post请求的url不能直接用浏览器打开,但可以通过 响应对象.text
方法,获得请求的内容
注意:
通过响应对象.text
方法得到的文本中,get请求的参数放在 args
中,post请求的参数放在 from
中,如:
\
2.5 获取json类型的数据
我们在爬取到某些网页源码的时候,可能出现下面这种内容:
可以看到上面这种数据与python中的字典相同,我们将这种形式的数据称为json数据
,但因为爬取的网页源码都是字符串形式的,若我们可以将其转化为字典形式的数据;就可以用字典的方法获取到其中想要的内容了
- 方法1:
import requests
import json # 导入json模块
# 1、目标网站
url = 'http://httpbin.org/get'
# 2、请求网站
r = requests.get(url)
print(r.status_code) # 查看状态码
data = r.text # 得到网页源码内容
print(type(data)) # 查看源码数据类型:字符串
# 3、通过json内置方法,将字符串数据转为字典数据
dict_data = json.loads(data)
print(dict_data) # 打印转化后的字典数据
print(type(dict_data)) # 字典型
# 4、通过字典的取值方式得到想要的数据
res = dict_data['url'] # 取出url后面的值
print(res)
- 方法2
语法格式:
响应对象.json()
,将json类型的数据转化为字典数据
import requests
# 1、目标网站
url = 'http://httpbin.org/get'
# 2、请求网站
r = requests.get(url)
# 3、将爬取到的网页源码转为字典类型的数据
dict_data = r.json() # 注意:只有当网页源码是json类型的数据时,才能使用该方法进行转换
print(dict_data)
print(type(dict_data)) # dict
2.6 获取二进制类型的数据
我们知道在网页中,图片、视频、音频等数据爬取下来后是以二进制形式存在的,这时若用 响应对象.text
方法获取数据,得到的是一堆乱码;所以我们需要用到新的方法;如下:
语法格式:
响应对象.content
import requests
# 1、目标站点:百度logo图片
url = 'https://www.baidu.com/img/baidu_jgylogo3.gif'
# 2、发送请求
r = requests.get(url)
data = r.content # 得到二进制数据
print(data) # 打印二进制数据
# 3、二进制数据可以直接保存至本地,不用解析内容
with open('百度logo','wb') as f:
f.write(data)
输出结果:
扩展:
bytes类型是指一堆字节的集合,在python中以b开头的字符串都是bytes类型
Bytes类型的作用:
- 在python中,数据转成二进制后不是直接以0101010的形式表示的,而是用一种叫bytes(字节)的类型来表示
- 计算机只能存储二进制,我们的字符、图片、视频、音乐等想存到硬盘上,也必须以正确的方式编码成二进制后再存。
记住一句话:在python中,字符串必须编码成bytes后才能存到硬盘上
2.7 添加headers的请求
headers
代表浏览器身份的标识,缺少的话服务器就无法识别你是一个浏览器用户,而是一个爬虫程序;从而请求失败或反馈错误的网页源码
headers可以在下方位置找到:
import requests
# 1、目标站点--知乎:https://www.zhihu.com/explore
url = 'https://www.zhihu.com/explore'
# 2、将身份信息headers构建为字典
h = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
# 3、发送请求
r = requests.get(url,headers=h)
# headers:用来携带伪装身份信息的参数
print(r.status_code) # 打印状态码
print(r.text) # 打印响应源码
注意
get
请求和post
请求传递的参数都只能是字典形式
,只有字典才拥有映射关系
3、Response响应
- 查看响应头部信息
语法格式:
响应对象.headers
- 查看网页是否跳转
语法格式:
响应对象.history
若跳转,返回[<Response [301]>]
;没有跳转,返回[]
- 禁止网页跳转参数
语法格式:
allow_redirects=False
;默认是True
写法如下:
响应对象 = requests.get(url,allow_redirects=False)
案例总结:
import requests
# 1、目标站点--http://www.jianshu.com
url = 'http://www.jianshu.com'
# 2、将身份信息headers构建为字典
h = {
'User-Agent': 'Mozilla/5.0 (Windows NT10.0; Win64; x64)AppleWebKit/537.36(KHTML, like Gecko)Chrome/92.0.4515.159 Safari/537.36'
}
# 3、发送请求,禁止网页跳转
r = requests.get(url,headers=h,allow_redirects=False)
# 4、查看响应头部信息
print(r.headers)
# 5、查看网页是否跳转
print(r.history)
注意:
爬虫在解析网页内容时,会依据网页结构的规则进行解析,若网页进行了跳转,尽管内容相同,但规则不一样就无法解析,导致爬取失败,所以一般我们会禁止网页跳转
扩展:常见网页状态码
200
表示请求成功301、302
:表示请求发生了跳转404
:表示没有找到该网页500、502、503
:表示服务器内部错误
4、高级操作
4.1 会话维持
4.1.1 引言
我们常见的网页基本都是使用的
http和https协议
的,而它们属于无状态协议
,对事物处理和请求无记忆
功能,所以我们每次请求网站都是一种独立
的状态;也就是我们每次访问同一种网页,服务器都会认为你是不同的用户;而爬虫程序通常会重复向服务器发送请求,这就导致在爬取某些需要登录的网站时,由于多次请求导致登录状态失效从而爬取失败
4.1.2 会话维持的作用
在请求网站时维持住某些参数,使用户的登录状态或身份信息保持不变
4.1.3 应用场景:模拟登陆
- 在requests中,如果直接利用get)或者 post()等方法的确可以做到模拟网页的请求,但这实际上是相当于不同的会话,每次请求都是独立的。
当我们向服务器发送请求后,服务器处理请求之后返回结果。这是一个独立的过程,再次向服务器发出请求,服务器做出响应又是一次独立的过程。
不会有一条网线一直连着你的电脑和服务器来完成你的所有请求 - 以上是因为我们访问每一个互联网页面,都是通过 HTTP 协议进行的,HTTP协议是无状态的协议。无状态是指协议对于事务处理没有记忆功能,缺少状态意味着,假如后面的处理需要前面的信息,则前面的信息必须重传,这样可能导致每次连接传送的数据量增大
- 建立会话对象让你能够跨请求保持某些参数,比如,仅使用HTTP协议的话,我们登录一个网站的时候,假如登录成功了,但是当我们访问该网站的其他网页的时候,该登录状态则会消失,此时还需要再登录一次,只要页面涉及更新,就需要反复的进行登录,这是非常不方便的。
- 所以此时,我们需要将对应的会话信息,比如登录成功等信息通过一些方式保存下来
- 比较常用的方式有两种:通过Cookie保存会话信息或通过Session保存会话信息。
为了解决这个问题,用于保持HTTP连接状态的Session和Cookie
就出现了
4.2 通过cookie维持会话
4.2.1 应用场景
遇到需要登录才能访问的网站,爬虫程序需要携带上登录后的信息,也就是
cookie
,才能访问
4.2.2 优缺点
- 好处
爬虫程序可以请求需要登录才能访问的网页 - 坏处
由于维持了身份信息,很容易被服务器发现你是爬虫程序,导致被反爬;这里我们可以通过更换登陆账号来解决
4.2.3 使用方法
import requests
# 1、目标站点--http://www.jianshu.com
url = 'http://www.jianshu.com'
# 2、构建身份信息,cookie中携带着登陆信息
h = {
'cookie' : '_ga=GA1.2.1869318034.1720129042; _ga_Y1EKTCT110=GS1.2.1721363033.3.0.1721363033.0.0.0; signin_redirect=https%3A%2F%2Fwww.jianshu.com%2F; read_mode=day; default_font=font2; locale=zh-CN; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%221907fae346dfe7-0bcd5af42c601e-26031e51-1327104-1907fae346e15a1%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_utm_source%22%3A%22desktop%22%2C%22%24latest_utm_medium%22%3A%22not-signed-in-bookmark-note%22%7D%2C%22%24device_id%22%3A%221907fae346dfe7-0bcd5af42c601e-26031e51-1327104-1907fae346e15a1%22%7D; Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1725524156; Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1725524156; HMACCOUNT=0F5095063C6FCA23',
'User-Agent': 'Mozilla/5.0 (Windows NT10.0; Win64; x64)AppleWebKit/537.36(KHTML, like Gecko)Chrome/92.0.4515.159 Safari/537.36'
}
# 3、发送请求
r = requests.get(url,headers=h)
cookie一般可以在下面找到:
4.3 通过session维持会话
cookie
只能记录当前请求时的登录信息,下一次请求时cookie就会改变
;而session
可以一直记住你的身份信息;可以用当前身份信息重复发起请求;通常用于爬取需要登录验证码的网站
4.3.1 使用方法
import requests
# 1、目标站点--http://www.baidu.com
url = 'http://www.baidu.com'
# 2、创建一个session对象
s = requests.session()
# 3、通过session对象发送请求
r1 = s.get(url) # 第一次请求
r2 = s.get('https://www.baidu.com/s?ie=UTF-8&wd=aa') # 第二次请求
# 两次请求的登录信息不变,这样就不用重新登陆了
总结:
cookie
只能维持当前的一种状态,当页面刷新或跳转,状态可能会失效,需要重新传入新的cookie;而session
可以记录这种状态;这样服务器就会记住你的身份,不会因页面刷新或跳转而失效
5、代理设置
5.1 引言
爬虫程序在爬取网站信息的时候,经常容易被反爬,从而被对方服务器禁用本地公网IP,导致当前网络无法访问该网站,这时就需要更换网络,也就是更换IP地址才能重新访问该网站
5.2 什么是代理?
从上面我们了解到爬虫在使用本地公网ip反复爬取数据时,可能会被对方服务器发现并禁用本地ip,这时我们就需要更换ip,那么这些ip怎样获取呢?一般来说重新换一个网络就行了,但爬虫需要的ip量非常大,只靠更换网络无法满足;所以我们需要到相关平台去购买ip,这种用于出售给我们使用ip我们称为代理
5.3 使用方法
一般会将代理,构建到字典中,在传入请求对象中;如:
p = {
'http:‘113.124.86.24:9999’,
'https:‘113.124.86.24:9999’,
}
http和https
代表要访问的网站是哪种协议,一般两种协议都会写上,请求对象会自动判断;后面的就是购买的代理IP地址
import requests
# 1、目标站点--http://www.baidu.com
url = 'http://www.baidu.com'
# 2、用字典组建代理(IP信息)
p = {
'http':'113.124.86.24:9999',
'https':'113.124.86.24:9999',
}
# 3、发送请求,传入代理
r = requests.get(url,proxies=p)
# proxies:用来接受代理的参数
6、功能扩展
6.1 超时设置
语法格式:
timeout = 数字
单位(秒),表示请求网站时,若超过这个时间还没有请求成功,程序会直接中断并显示一些异常信息
使用案例:
import requests
# 1、目标站点--http://www.baidu.com
url = 'http://www.baidu.com'
# 3、发送请求,设置超时时间
r = requests.get(url,timeout=3)
# timeout:设置超时时间,这里表示超过3秒还没有请求成功,程序报错,若请求成功,程序正常运行
print(r.status_code)
6.2 异常处理
语法格式:
try:
代码
except:
代码
# 这里表示,若 try 后面的代码出现报错,程序不会停止运行,
而是去执行 except 后面的代码,执行完后继续往后运行;没有报错就不会运行except后的代码
上面的超时设置,我们可以结合异常处理的功能来配合使用;如下:
import requests
# 1、目标站点--http://www.baidu.com
url = 'http://www.baidu.com'
# 3、发送请求
try:
r = requests.get(url,timeout=3)
print(r.status_code)
except:
print('网站访问超时!!!')
# 上面表示若请求超时失败,则打印except后的提示信息
7、知识汇总:爬虫小案例
import requests
# 1、目标站点--http://www.baidu.com
url = 'http://www.baidu.com'
# 2、构建参数信息
p = {
'prod':'pc_his',
'from':'pc_web',
'json':'1',
'sid':'26350',
'hisdata':'[{"time":1677678043,"kw":"python"},{"time":1677678045,"kw":"就是"},{"time":1677678048,"kw":"中文"},{"time":1677678058,"kw":"会与","fq":2},{"time":1677678099,"kw":"代理"}]',
'_t':'1677678316431',
'req':'2',
'bs':'就',
'csor':'0',
}
# 3、构建身份信息
h = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0;Win64; x64) AppleWebKit/537.36 (KHTML, likeGecko)Chrome/110.0.0.0 Safari/537.36'
'cookie' : 'pglt-edgeChromium-ntp=171; pglt-edgeChromium-dhp=171; _C_Auth=; MicrosoftApplicationsTelemetryDeviceId=936b634c-82b1-479e-8315-4b78f3a17053; MUID=1F2B4441A70A6D771DF856B0A6246C1B; APP_ANON=A=10F5DE3E3942863F3E282555FFFFFFFF; aace=%7b%22child%22%3a0%7d; els=%7b%22account_type%22%3a%22MSA%22%7d; RC=245.20.HKDCNYLITE=currency=avbknm:245.20.CNYJPYLITE=currency=av4yk2:245.20.JPYCNYLITE=currency=avdzk2:245.20.GBPCNYLITE=currency=avybkr:245.20.USDJPYLITE=currency=avyomw:245.20.USDCNYLITE=currency=avym77:245.20.EURCNYLITE=currency=av8u5r; MSFPC=GUID=9a7a4cdd793745a8a91bc293b2462e27&HAS'
}
# 3、发送请求
r = requests.get(url,params=d,headers=h)
# 4、获取源码
json_data = r.json()
print(json_data)
# 5、解析源码
g_data = json_data['g']
print(g_data)
for i in g_data:
data = i['q']
print('最终数据:',data)
# 6、保存数据
with open('dada.txt','a',encoding='utf-8') as f:
f.write(data)
f.close()
注意:
上面案例中的网站,身份信息可能失效,直接运行会报错,大家可根据方法自行选定目标网站进行尝试