网络爬虫笔记-requests库
一、requests库的安装
首先,打开Anaconda的命令提示符界面;然后输入下面的代码即可安装requests库。
pip install requests
二、get请求
2.1 什么是get请求
当我们在浏览器中输入一个网址(网址也可以叫做URL)并回车,这便发起了一个get请求。get请求的参数会直接出现在我们输入的URL网址中。
2.2 一个简单的get请求实例
import requests
test_url="http://httpbin.org/get"#这是get请求的测试网址
r = requests.get(test_url)#向服务器发起get请求
print(r.text)#将网页呈现的内容以文本的形式输出
输出结果
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.27.1",
"X-Amzn-Trace-Id": "Root=1-63319da6-1be94fd22ef00911623608ad"
},
"origin": "183.195.56.89",
"url": "http://httpbin.org/get"
}
2.3 带参数的get请求
假如我们要在上述的测试地址中加入两个参数,将地址写成“http://httpbin.org/get?name=MacroSpider&age=1” ,我们再来看一下访问该地址的输出:
import requests
test_url="http://httpbin.org/get?name=MacroSpider&age=1"
r = requests.get(test_url)#向服务器发起get请求
print(r.text)#输出服务器返回的文本
输出结果
{
"args": {
"age": "1",
"name": "MacroSpider"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.27.1",
"X-Amzn-Trace-Id": "Root=1-63319f01-4ea41d4e411b438b209ccd80"
},
"origin": "183.195.56.89",
"url": "http://httpbin.org/get?name=MacroSpider&age=1"
}
与未加参数的输出内容对比,在args处,多了我们输入的参数,说明参数输入成功。其实我们也可以通过下面的方法来输入get参数
import requests
test_url="http://httpbin.org/get"
data = {"name":"MacroSpider","age":1}
r = requests.get(test_url,params=data)#向服务器发起get请求
print(r.text)#输出服务器返回的文本
我们可以发现,这两种方法都可以发送带参数的get请求,第二种方法更加的简介和方便操作。 上述网站返回的文本是一个字典格式的文本,针对字典格式的文本,我们可以用json方法,将其转化为字典,以此来方面数据的提取。
rdic = r.json()
print(type(rdic),rdic["args"])
输出结果
<class 'dict'> {'args': {'age': '1', 'name': 'MacroSpider'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, br', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.27.1', 'X-Amzn-Trace-Id': 'Root=1-63319fb9-106024135b7e500b07940589'}, 'origin': '183.195.56.89', 'url': 'http://httpbin.org/get?name=MacroSpider&age=1'} {'age': '1', 'name': 'MacroSpider'}
通过json方法,我们将文本格式的数据转化成了字典格式,这样后面通过字典的key即可获取所需数据
2.4 抓取知乎数据
import requests
import re
headers = {"user-agent":"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"}
#headers中的user-agent字段的目的是设置请求头,将该请求伪装成是浏览器的请求,有些网站如果不伪装会无法抓取数据
test_url = "https://www.zhihu.com/explore"
r = requests.get(test_url,headers=headers)#向服务器发起get请求
titles = re.findall(r"question\/[0-9]+\"\>(.*?)\</a\>",r.text)#利用正则表达式解析网页返回的文本,并获取目标数据
print(titles)
输出结果
['湖南两人穿「和服」餐馆就餐,阿姨劝阻遭怼,如何看待此事?', '为什么有些老顾客吃着吃着就不再来照顾生意了?', '王毅阐述「六点主张」,会后许多国家代表等候与中方握手交流,表示对倡议的支持与认可,如何看待这一细节?', '如何评价电影《隐入尘烟》票房过一亿突遭下架?', '台媒称「佩洛西专机降落松山机场」,有哪些信息值得关注?', '布林肯称「是否访问台湾将由佩洛西自行决定」,推特网友嘲讽布林肯逻辑,如何评价他的表态?', '华春莹发了一组中美对比图「破坏与建设」,形成了怎样的对比?释放了哪些信号?', '俄外长称西方国家向乌克兰提供了武器、情报,实质上已经参加乌克兰冲突,如何看待这一表态?']
上述抓取的是下图红色方框内的内容
2.5 抓取二进制数据
图片、音频和视屏等都是二进制数据,不能直接通过文本获取,需要抓取这些数据的二进制代码,并写进文件中。
import requests
test_url = "https://static.zhihu.com/heifetz/assets/loginBackgroundImg.2c81e205.png"#知乎图片地址
r = requests.get(test_url)#向服务器发起get请求
with open("zhihu.png","wb") as f:#写入二进制数据
f.write(r.content)
这里用到了open
函数,第一个参数代表文件名,第二参数代表以二进制形式打开。r.content
可以获取二进制信息。
运行上述代码即可在代码的文件夹中生成一个名称为“zhihu”的图片,即下面的图片
3 post请求
post请求大多在表单提交时发起。例如登录表单,输入用户名和密码,点击登录。其数据通常以表单的形式提交,而不在URL中体现。
import requests
test_url="http://httpbin.org/post"#与前面的get测试网址相比,这里将get变成了post
data = {"name":"MacroSpider","age":1}
r = requests.post(test_url,data=data)#get是用params,而post是用data
print(r.text)
输出结果
{
"args": {},
"data": "",
"files": {},
"form": {
"age": "1",
"name": "MacroSpider"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br",
"Content-Length": "22",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.27.1",
"X-Amzn-Trace-Id": "Root=1-633455ac-0656f7c4387ef4a22bc689c2"
},
"json": null,
"origin": "183.195.59.65",
"url": "http://httpbin.org/post"
}
从返回结果来看,我们传输的数据,成功的出现在了form部分里面,说明post请求成功。
4 响应
向网站发送请求后,会得到来自网站的数据,这些数据包括状态码、响应头、cookies等
import requests
headers = {"user-agent":"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"}
r = requests.get("http://www.jianshu.com",headers=headers)
print(type(r.status_code),r.status_code)#获取请求状态,可以知道是否成功访问网页
print(type(r.headers),r.headers)#获取请求头
print(type(r.cookies),r.cookies)#获取cookies,cookies里面包含你的登录信息,每次向网页发起请求时,将cookies作为参数传递给服务器,以便服务器识别信息
print(type(r.url),r.url)#获取url
print(type(r.history),r.history)
输出结果
<class 'int'> 200
<class 'requests.structures.CaseInsensitiveDict'> {'Date': 'Wed, 28 Sep 2022 14:21:51 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'X-Content-Type-Options': 'nosniff', 'ETag': 'W/"52e6922c5806bc60b810a4e340d2621e"', 'Cache-Control': 'max-age=0, private, must-revalidate', 'Set-Cookie': 'locale=zh-CN; path=/', 'X-Request-Id': 'f2e8ef8d-f7f2-4484-bd54-e7c5e737f002', 'X-Runtime': '0.006302', 'Content-Encoding': 'gzip'}
<class 'requests.cookies.RequestsCookieJar'> <RequestsCookieJar[<Cookie locale=zh-CN for www.jianshu.com/>]>
<class 'str'> https://www.jianshu.com/
<class 'list'> [<Response [301]>]
5 高级用法
5.1 文件上传
文件上传需使用post方法
import requests
files = {"file":open("zhihu.png","rb")}#读取之前从知乎下载的图片
r = requests.post("http://httpbin.org/post",files=files)#附件上传用的是files参数
print(r.text)
输出结果
{
"args": {},
"data": "",
"files": {
"file": "data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAAAt..."
},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br",
"Content-Length": "125904",
"Content-Type": "multipart/form-data; boundary=ec39a45f82cb7d150cbe9af220a06903",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.27.1",
"X-Amzn-Trace-Id": "Root=1-63345abc-46319ee56079b0af769d96ae"
},
"json": null,
"origin": "183.195.59.65",
"url": "http://httpbin.org/post"
}
从返回的结果来看,在files部分多出了许多数据,这正是我们上传的图片(由于输出内容较多,上面的内容省略了一部分)。文件上传需要一个单独的files字段,而不是data,form等字段。
5.2 Cookies的使用
Cookies里面保存了我们的登录信息,服务器通过Cookier来判断是哪个用户登录,从而做出相应的回应。例如有些网站需要登录之后才能访问,这时我们可以
先在网页端,登录网页。然后查看登录后Cookies信息,最后在爬取数据的时候,以请求头的形式将该Cookies值传递给服务器,这样便可以正常爬取数据了。
案例:使用Cookies维持登录状态
import requests
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
"Cookie":"_ga=GA1.2.1338053426.1661864805; cloud-..."
}
r = requests.get("https://www.zhihu.com",headers=headers)
print(r.text)
这种方式只对部分网站是有效的,有的网站通过这用方式也不能成功登录。代码中cookie需换成自己的cookies
获取登录后cookie信息(以edge浏览器为例)
1、进入知乎网页,登录你的账号;
2、在网页空白处右键,然后选择“检查”;
3、此时右侧会弹出界面,选择界面中的“网络”;
4、重新刷新一下页面(右键网页空白处,在弹出的界面中选择“刷新”);
5、此时“网络”处信息会重新刷新。然后按照下图的顺序便可得到cookie信息。
5.3 会话维持
我们通过post或get方法,每发送一次请求就相当于重新打开一次浏览器。每一次操作都是新的操作和原来的操作互不相关。他并不能像我们用浏览器浏览网页一样,只需要打开一次浏览器,然后通过点击和输入等一些操作获取网页的信息。为了达到这种效果我们就需要用到会话维持技术。
import requests
r = requests.get("http://httpbin.org/cookies")#cookie的测试网址
print(r.text)
输出结果
{
"cookies": {}
}
上面为网页最初返回的内容。该cookies的测试网址会返回一个空的cookies,下面我们给该网站设置一个cookies
import requests
r = requests.get("http://httpbin.org/cookies/set/numbers/123456789")
print(r.text)
输出结果
{
"cookies": {
"numbers": "123456789"
}
}
从返回结果来看,cookie设置成功。下面看一下不使用会话维持能否获取设置好cookies的内容。
import requests
requests.get("http://httpbin.org/cookies/set/numbers/123456789")#设置cookies
r = requests.get("http://httpbin.org/cookies")
print(r.text)
输出结果
{
"cookies": {}
}
从运行结果来看,即便我们设置了cookies,但是当我们再次发起get请求时,还是获取不到设置的cookies,下面再看一下运用会话维持的效果;
import requests
s = requests.Session()
s.get("http://httpbin.org/cookies/set/numbers/123456789")#设置cookies
r = s.get("http://httpbin.org/cookies")
print(r.text)
输出结果
{
"cookies": {
"numbers": "123456789"
}
}
从返回结果来看,通过会话维持,即便我们再次发起请求,也可以成功获取之前设置的cookies值
5.4 SSL证书验证
我们在访问国家统计局(https://data.stats.gov.cn) 数据查询网站时,浏览器或许会跳出如下提示:
这时我们用requests向该网站发起请求时,便会报错。
import requests
r = requests.get("https://data.stats.gov.cn")
print(r.status_code,r.text)
输出结果
SSLError: HTTPSConnectionPool(host='data.stats.gov.cn', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1129)')))
报错内容为:SSLError,这是因为该网站没有被官方CA机构认证,从而不能验证通过。此时我们可以通过设置verify的方法来规避这种认证。从而正常访问网页。
import requests
from requests.packages import urllib3
urllib3.disable_warnings()#因为我们忽略验证,系统会有警告,通过该语句可以忽略警告
r = requests.get("https://data.stats.gov.cn",verify=False)
print(r.status_code)#返回的结果为200,代表访问成功
5.5 代理设置
有些网站,在测试的时候请求几次可以正常获取内容。但当大规模爬取的时候,就会弹出验证码,甚至封禁客户端的IP,导致不能正常抓取内容。而这时就需要用代理来解决这一个问题。代理的参数为proxies
import requests
proxies = {
"http":"http://10.10.1.10:3128", #如果代理地址需要用到用户名和密码可以这样写http://user:password@10.10.1.10:3128/
"https":"http//10.10.1.10:1080"
}
requests.get("https://www.taobao.com",proxies=proxies)
上述的代码并不能有效运行,因为代理是无效的,在实际使用时可以换成自己的代理试一下。
5.6 超时设置
有时服务器反应比较慢,我们等了很长时间都没有得到响应,但系统又没有报出异常。这时我们可以通过timeout参数设置一个等待时间,如果超过这个时间没有响应,则系统会有超时提示。
import requests
r = requests.get("https://www.baidu.com",timeout=1)#设置超时时间为1秒,如果一秒内没有反应则弹出提示。
print(r.status_code)
参考书目:
《Python3网络爬虫开发实战》_崔庆才
- 本文章,首发于微信公众号:宏蜘蛛,原文链接:网络爬虫笔记-requests库