requests 是用 python 语言编写的一个开源的HTTP库,可以通过 requests 库编写 python 代码发送网络请求,其简单易用,是编写爬虫程序时必知必会的一个模块。
requests 模块的作用
发送网络请求,获取响应数据。
中文文档: Requests: 让 HTTP 服务人类 — Requests 2.18.1 文档
requests 模块的安装
安装命令如下:
pip install requests
或者
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
具体安装运行如下图所示:
查看安装好的 requests 模块的信息
pip show requests
具体运行如下图所示:
01_requests 模块的基本使用
知识点:
- 掌握 requests 发送 GET 请求
- 掌握 response 对象的基本属性
- 掌握 response.text 和 response.content 的区别
- 掌握 requests 发送自定义请求头的方式
- 掌握 requests 发送带参数的get请求
1.1 requests 发送 GET 请求
使用 requests 模块发送 GET 请求的语法是: requests.get(url), 调用完该方法之后会返回一个 response 响应对象。
需求:通过 requests 向百度首页发送请求,获取百度首页的数据
# 1. 导入request模块
import requests
# 2. 准备目标url地址
url = 'https://www.baidu.com'
# 3. 向目标url地址发送get请求
response = requests.get(url)
# 4. 打印响应内容
print(response.text)
运行代码结果如下:
1.2 response 响应对象
观察上边代码运行结果发现,有好多乱码;这是因为编解码使用的字符集不同早造成的;我们尝试使用下边的办法来解决中文乱码问题。
代码如下:
# 1. 导入request模块
import requests
# 2. 准备目标url地址
url = 'https://www.baidu.com'
# 3. 向目标url地址发送get请求
response = requests.get(url)
# 4. 打印响应内容
# print(response.text)
print(response.content.decode())
运行代码结果如下:
1.2.1 response.content 和 response.text 的区别
response.content
- 返回类型: bytes
- 解码类型: 没有指定,原始响应内容,没有进行解码
- 指定编码方式:
response.content.decode('指定编码字符集')
- 注意:
response.content.decode()
默认使用 utf-8 编码方式
response.text
- 返回类型: str
- 解码类型: requests 模块自动根据 HTTP 头部对响应的编码作出有根据的推测,推测的文本编码
response.text = response.content.decode('推测出的编码字符集')
获取网页源码的方式:
- response.content.decode()
- response.content.decode('gbk')
- response.text
以上三种方法从前往后尝试,能够100%的解决所有网页解码的问题, 推荐优先使用: response.content.decode()
1.2.2 response 响应对象其他属性和方法
- response.url : 响应的url地址,有时候响应的 url 地址和请求的 url 地址不一样。
- response.status_code : 获取响应状态码。
- response.request.headers : 获取响应对应的请求头信息。
- response.headers : 获取响应头信息。
- response.request._cookies : 响应对应请求携带的cookie,返回cookieJar类型。
- response.cookies : 响应时设置的 cookie,返回cookieJar类型。
- response.json() : 自动将 json 字符串类型的响应内容转换为 python 对象(dict or list)。
示例代码如下:
# 1. 导入request模块
import requests
# 2. 准备目标url地址
url = 'https://www.baidu.com'
# 3. 向目标url地址发送get请求
response = requests.get(url)
# 4. 打印响应内容
print(response.url) # 打印响应的url
print(response.status_code) # 打印响应的状态码
print(response.request.headers) # 打印响应对象的请求头
print(response.headers) # 打印响应头
print(response.request._cookies) # 打印请求携带的cookies
print(response.cookies) # 打印响应设置的cookies
示例代码运行结果如下:
1.2.3 练习-保存网络图片
需求: 将图片http://www.itcast.cn/2018czgw/images/logo2.png
保存到本地。
思考:
- 以什么方式打开文件。
- 保存什么格式的内容。
分析:
- 图片的url地址:
http://www.itcast.cn/2018czgw/images/logo2.png
- 利用 requests 模块发送请求,获取到图片的响应。
- 以二进制的方式打开文件,并将 response 响应的二进制内容写入到文件。
完整代码如下:
# 1. 导入request模块
import requests
# 2. 准备目标url地址
url = 'http://www.itcast.cn/2018czgw/images/logo2.png'
# 3. 向目标url地址发送get请求
response = requests.get(url)
# 4. 打开文件,将数据写入到文件中
with open('itcast.png', 'wb') as f:
# 写入响应内容的二进制数据
f.write(response.content)
1.3 requests 请求时设置请求头
在最开始,我们书写了一下代码,获取了一下百度首页的内容:
# 1. 导入request模块
import requests
# 2. 准备目标url地址
url = 'https://www.baidu.com'
# 3. 向目标url地址发送get请求
response = requests.get(url)
# 4. 打印响应内容
print(response.content.decode())
运行以上代码的结果如下:
接下来,我们对比一下,使用浏览器查看的百度的源码和我们代码中拿到的源码有什么区别。
打开浏览器,访问百度首页,然后 鼠标右键 --> 查看网页源代码
可以看到,很明显使用浏览器获取到的百度首页的内容要比使用代码获取到的内容要多得多。这是为什么呢?
回顾爬虫的概念:模拟浏览器,欺骗服务器,获取和浏览器一致的内容, 所以在这里我们需要带上一些请求头信息。
查看一下浏览器的请求头信息:鼠标右键 --> 检查 --> 打开Network --> 地址栏访问百度,抓包,查看请求信息
再在代码中,使用 response.requests.headers 查看使用 requests 模块发送请求时携带的请求头信息:
对比一下,很明显的,代码中的 User-Agent 和 浏览器中的完全不一样,前面我们也说过,User-Agent 是浏览器的身份标识,而代码中直接发送的是 python-requets/2.25.1
这样服务器很明显的就知道我们不是使用正常的浏览器访问服务器,所以返回的数据就比较少。
1.3.1 设置请求头的语法
response = requests.get(url, headers={})
- headers 参数接收的字典形式的请求头
- 请求头字段名作为字典的 key,字段名对应的值作为字典的 value。
例如:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36
作为 headers 的参数,可以写为:
{"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"}
1.3.2 设置请求头完整代码实现
# 1. 导入request模块
import requests
# 2. 准备目标url地址
url = 'https://www.baidu.com'
# 准备请求头字典
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"
}
# 3. 向目标url地址发送get请求
response = requests.get(url, headers=headers)
# 4. 查看请求头信息
print(response.request.headers)
# 5. 打印响应内容
print(response.content.decode())
运行结果如下图所示:
很明显,拿到的内容和使用浏览器拿到的网页源码内容就是一样的了。
1.4 发送带查询参数的请求
我们在使用百度搜索的时候,经常会发现 URL 地址中会有一个 ? ,该问号后面的就是查询参数,又叫做查询字符串参数。
1.4.1 requests请求携带查询参数的语法
语法格式如下:
response = requests.get(url, params={})
- params参数接收的是一个字典。
- 查询参数中,等号左边的内容作为字典的 key,等号右边的内容作为字典的 value。
- 注意点:在url地址中, 很多查询参数是没有用的,比如百度搜索的url地址,其中参数只有一个字段有用,其他的都可以删除。如何确定那些请求参数有用或者没用:挨个尝试! 对应的,在后续的爬虫中,遇到很多参数的url地址,都可以尝试删除参数。
1.4.2 发送带查询参数请求的应用
需求:实现在百度中搜索 传智播客
实现方式1:对 传智播客_百度搜索 发起请求可以使用 requests.get(url, params=kw) 的方式
实现代码如下所示:
# 1. 导入request模块
import requests
# 2. 准备目标url地址
url = 'https://www.baidu.com/s?'
# 准备请求头字典
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"
}
# 准备请求参数的字典
params = {
"wd": "传智播客"
}
# 3. 向目标url地址发送get请求
response = requests.get(url, headers=headers, params=params)
# 4. 打印响应的内容
print(response.content.decode())
上述代码运行结果如下图所示:
实现方式2:直接对 传智播客_百度搜索 完整的url地址进行请求,不使用 params 参数
实现代码如下:
# 1. 导入request模块
import requests
# 2. 准备目标url地址
url = 'https://www.baidu.com/s?wd=传智播客'
# 准备请求头字典
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"
}
# 3. 向目标url地址发送get请求
response = requests.get(url, headers=headers)
# 4. 打印响应的内容
print(response.content.decode())
以上代码运行结果如下所示:
02_requests 模块的深入使用
知识点:
- 了解 GET 和 POST 请求的区别
- 掌握 使用 requests 发送 POST 请求
- 了解 代理IP的分类
- 掌握 requests 模块使用代理IP的方法
2.1 requests 模块发送POST请求
思考: 那些地方会使用到 POST 请求?
- 登录注册:POST 比 GET 更安全。
- 需要传输大文本内容的时候,POST请求对数据长度没有要求。
所以同样的,我们的爬虫也需要在这两个地方会去模拟浏览器发送post请求。
补充:GET 请求和 POST 请求的区别
GET | POST | |
---|---|---|
后退按钮/刷新 | 无害 | 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。 |
书签 | 可收藏为书签 | 不可收藏为书签 |
历史 | 参数保留在浏览器历史中。 | 参数不会保存在浏览器历史中。 |
对数据长度的限制 | 当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 | 无限制。 |
对数据类型的限制 | 只允许 ASCII 字符。 | 没有限制。也允许二进制数据。 |
安全性 | 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或者其他敏感信息的时候决不能使用GET。 | POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。 |
可见性 | 数据在 URL 中对所有人都是可见的。 | 数据不会显示在 URL 中。 |
2.1.1 requests 发送 POST 请求语法
语法格式如下:
response = requests.post(url, data={}, headers={}, params={})
- data参数接收的数据类型是字典。
- POST请求体(form data)中,冒号左边的作为字典的 key,冒号右边的作为字典的 value。
如下图所示:
将请求体(form data)中的数据转换为字典:
data = {
"username": "admin",
"password": "admin"
}
2.1.2 案例
登录页面 URL 地址: http://manager-health-java.itheima.net/login.html
案例分析
抓包分析,找到登录请求的url地址
-
右键检查 --> Network
- 用户名和密码输入框输入用户名和密码: 用户名 admin,密码 admin,然后点击登录,抓取请求
- 根据抓包发现,登录的 URL 地址为:(登录成功之后会进行重定向到首页,所以响应状态码是302)
- 请求体数据为:
-
最终分析出:
-
POST 请求 URL 地址为:
http://manager-health-java.itheima.net/login.do
-
请求方式为:
POST
-
请求体参数为:
data = { "username": "admin", "password": "admin" }
-
案例代码实现
完整代码如下:
import requests
# 1. 准备登录的url地址,请求头,请求体数据
login_url = "http://manager-health-java.itheima.net/login.do"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"
}
data = {
"username": "admin",
"password": "admin"
}
# 2. 发起登录请求
response = requests.post(login_url, data=data, headers=headers)
# 打印登录成功之后的响应状态码和响应的内容
print(response.status_code)
print(response.content.decode())
上述代码运行结果如下:
响应状态码:
200
2.2 requests 使用代理
每次在使用浏览器请求一个网站的时候,服务器是可以获取到当前客户端的 IP 地址的,使用爬虫程序去请求服务器的速度和频率是特别快的,这样的话,我们使用同一台电脑上的浏览器去请求别人的服务器,会被服务器识别到,这样可能就会将我们的 IP 地址封掉。为了不让服务器将我们的 IP 地址封掉,在发送请求的时候可以使用代理 IP。
2.2.1 使用代理 IP 的目的
- 让服务器以为是不同的客户端在请求
- 防止我们的真实地址被泄露,防止被追究
2.2.2 代理的使用过程
-
代理IP 是一个IP,指向的是一个代理服务器
-
代理服务器能够帮我们向目标服务器转发请求
2.2.3 代理 IP 的分类
根据代理 IP 的匿名程度,代理 IP 可以分为以下三类:
分类名称 | 特点 | 服务器接收的请求头信息 |
---|---|---|
透明代理 | 透明代理虽然可以直接“隐藏”你的IP地址,但是还是可以查到你是谁。 | REMOTE_ADDR = Proxy IP HTTP_VIA = Proxy IP HTTP_X_FORWARDED_FOR = Your IP |
匿名代理 | 使用匿名代理,别人只能知道你用了代理,无法知道你是谁。 | REMOTE_ADDR = Proxy IP HTTP_VIA = Proxy IP HTTP_X_FORWARDED_FOR = Proxy IP |
高匿代理 | 无法发现你是在用代理,所以是最好的选择毫无疑问使用高匿代理效果最好。 | REMOTE_ADDR = Proxy IP HTTP_VIA = not determined HTTP_X_FORWARDED_FOR = not determined |
根据网站所使用的协议不同,需要使用相应协议的代理服务。从代理服务请求使用的协议可以分为:
- http代理:目标url为http协议
- https代理:目标url为https协议
- socks隧道代理(例如socks5代理)等:
- socks 代理只是简单地传递数据包,不关心是何种应用协议(FTP、HTTP和HTTPS等)。
- socks 代理比http、https代理耗时少。
- socks 代理可以转发http和https的请求
2.2.4 requests 模块中使用代理
为了让服务器以为是不同的客户端在请求;为了防止频繁向一个域名发送请求被封 IP,所以我们需要使用代理 IP;那么我们接下来要学习requests 模块是如何使用代理 IP 的。
语法格式如下:
response = requests.get(url, proxies={})
proxies 参数接收的数据类型为字典。
字典的格式如下:
proxies = {
"协议类型": "协议类型://代理IP地址:端口号"
}
例如:
proxies = {
# 目标地址为 http 协议,会使用 http 这个 key 对应的代理服务
"http": "http://113.121.255.26:9999",
# 目标地址为 https 协议,会使用 https 这个 key 对应的代理服务
"https": "https://219.151.157.130:3128"
}
免费代理 IP 网站
在学习阶段,我们直接在网上找一些免费的代理去使用即可,免费的代理的质量不是很好,真正在公司会去购买付费的高质量的代理,或者自己去搭建代理服务器。
2.2.5 案例 - 使用代理 IP 请求唱吧
完整代码如下:
# 1. 导入request模块
import requests
# 2. 准备目标url地址
url = 'http://changba.com/now/stars/index.html'
# 准备请求头字典
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"
}
# 准备代理IP的字典
proxies = {
'http': 'http://113.108.190.50:8080'
}
# 3. 向目标url地址发送get请求
response = requests.get(url, headers=headers, proxies=proxies)
# 4. 打印响应的内容
print(response.content.decode())
运行结果如下:
03_requests 请求携带 Cookie
知识点:
- 了解 爬虫中为什么要使用 Cookie
- 掌握 在请求头中携带 Cookie
- 掌握 使用cookies参数携带 Cookie
- 掌握 使用requests.session 进行状态保持
3.1 爬虫中使用Cookie
为了能够通过爬虫获取到登录后的页面,或者是解决通过cookie的反扒,需要使用request来处理cookie相关的请求
3.1.1 爬虫中携带Cookie的利弊
- 带上 Cookie 的好处
- 能够访问登录后的页面
- 能够实现部分反反爬
- 带上 Cookie 的弊端
- 一套cookie往往对应的是一个用户的信息,请求太频繁有更大的可能性被对方识别为爬虫
- 那么上面的问题如何解决 ?使用多个账号
3.1.2 requests中使用 Cookie的方法
使用requests携带cookie有三种方法:
- cookie字符串放在headers中,设置 Cookie 请求头
- 把cookie字典放传给请求方法的cookies参数接收
- 使用requests提供的session模块发送请求
3.2 Cookie 添加在 headers 中
网站经常利用请求头中的 Cookie 字段来做用户访问状态的保持,那么我们可以在 headers 参数中设置 Cookie 请求头,模拟普通用户的请求。我们以传智健康登陆为例:
3.2.1 抓包找到登录之后的Cookie
-
打开浏览器,右键检查,点击 Network,勾选 Preserve log
-
输入账号和密码之后,点击登录。
-
访问一个登录之后才可以访问的页面,例如: 传智健康
-
找到Network中对应的抓到的包,查看在访问时携带的 User-Agent 和 Cookie 的信息
3.2.2 完成代码
- 从浏览器中复制User-Agent和Cookie
- 浏览器中的请求头字段和值与headers参数中必须一致
- headers请求参数字典中的Cookie键对应的值是字符串
完整代码如下:
import requests
# 1. 准备目标url地址
url = 'http://manager-health-java.itheima.net/pages/main.html'
# 2. 准备请求头信息,cookie 和 User-Agent,(从浏览器抓包复制)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
"Cookie": "JSESSIONID=4BBDB822771C712E3570B8AD3BED780F"
}
# 3. 发送请求,获取响应数据
response = requests.get(url, headers=headers)
# 4. 查看响应的内容
print(response.content.decode())
运行代码验证结果:
登录之后访问该页面,会显示出来对应的左侧的菜单信息,我们查看一下在代码中获取到的响应内容中,是否包含着对应的菜单信息即可。
3.3 使用 Cookies 参数
上一小节中,我们在请求头 headers 中携带着登录之后的 Cookie 信息,我们也可以使用专门的 cookies 参数来携带 Cookie。
3.3.1 Cookies 参数语法以及格式
-
cookies参数的格式:字典
cookies = {"Cookie的name": "Cookie的Value"}
- 该字典对应请求头中Cookie字符串,以分号、空格分割每一对字典键值对
- 等号左边的是一个cookie的name,对应cookies字典的key
- 等号右边对应cookies字典的value
-
cookies参数的使用方式:
response = requests.get(url, cookies={})
-
注意: cookie一般是有过期时间的,一旦过期需要重新获取
3.3.2 使用cookies参数完成登录传智健康
- 登录传智健康,获取到登录之后的cookie字符串
- 将浏览器抓包获取到的cookie字符串,转换成字典,以便用于发送请求时传递给cookies参数。
完整代码如下:
import requests
# 1. 准备目标url地址
url = 'http://manager-health-java.itheima.net/pages/main.html'
# 2. 准备请求头信息,User-Agent,(从浏览器抓包复制)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
# 准备cookies字典
cookie_dict = {
'JSESSIONID': '14C7DFBF244EB81DC281FC1B96EF88D6'
}
# 3. 发送请求,获取响应数据
response = requests.get(url, headers=headers, cookies=cookie_dict)
# 4. 查看响应的内容
print(response.content.decode())
对比网页内容和使用代码获取到的网页响应内容:
发现,代码中获取到的响应内容和页面中的内容是一致的,表示我们使用 cookies参数携带cookie登录传智健康是成功的。
cookie有过期时间 ,所以直接复制浏览器中的cookie可能意味着下一程序继续运行的时候需要替换代码中的cookie,对应的我们也可以通过一个程序专门来获取cookie供其他程序使用;当然也有很多网站的cookie过期时间很长,这种情况下,直接复制cookie来使用更加简单。
补充:将浏览器复制的含有多个Cookie的字符串转换为字典
cookies_dict = {
cookie.split('=')[0]:cookie.split('=')[1] for cookie in cookies_str.split('; ')
}
3.4 使用 requests.session 携带Cookie
前面使用手动的方式使用cookie,那么有没有更好的方法在requets中携带cookie呢?
requests 提供了一个叫做session类,来实现客户端和服务端的会话保持
会话保持有两个内涵:
- 自动保存cookie,下一次请求会带上前一次的cookie
- 实现和服务端的长连接,加快请求速度
3.4.1 使用方式
session = requests.session() # 实例化session类对象
response = session.get(url, headers, ...)
response = session.post(url, data, ...)
- session对象发送get或post请求的参数,与requests模块发送请求的参数完全一致
3.4.2 使用 requests.session 登录传智健康
-
登录页面 url 地址: 传智健康
-
先抓包获取到登录传智健康的登录 url 地址,以及登录需要的参数
- 先使用 request.session 完成登录,获取登录之后的 cookie
- 在使用 request.session 对象请求登录之后的页面。
完整代码如下:
import requests
# 1. 准备登录的url地址(抓包获取到的登录的post url地址)
login_url = "http://manager-health-java.itheima.net/login.do"
# 准备请求头User-Agent
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
# 准备请求体字典
data = {
"username": "admin",
"password": "admin"
}
# 2. 创建session对象
session = requests.session()
# 3. 使用session对象发送post请求 登录传智健康
session.post(login_url, headers=headers, data=data)
# 使用 session对象再次请求登录之后的url地址
url = "http://manager-health-java.itheima.net/pages/main.html"
# 发送请求 获取响应
response = session.get(url, headers=headers)
# 4. 打印响应内容
print(response.content.decode())
04_案例-百度贴吧爬虫
4.1 需求
- 给定一个贴吧名字,给定要抓取的页数。
- 将贴吧的每一页数据保存到html中。
4.2 需求分析
-
打开百度贴吧首页:登录_百度贴吧
-
搜索访问进入某一个贴吧中,这里以传智播客贴吧为例: https://tieba.baidu.com/f?kw=传智播客
-
上述过程中,我们可以分析出来,在url地址中的 kw 参数,对应的就是我们要访问的贴吧的名字。我们可以根据给定的贴吧名字进行替换要抓取的贴吧的名字。
-
进入到传智播客贴吧中,我们目前看到的就是第一页的数据,需求中,我们是需要获取到多页的数据的,那么我们就需要去分析一下,每一页的url地址的规律,从而构造出多页的url地址。
-
页面url地址规律分析
第一页的url地址: https://tieba.baidu.com/f?kw=传智播客 第二页的url地址: https://tieba.baidu.com/f?kw=传智播客&pn=50 第三页的url地址: https://tieba.baidu.com/f?kw=传智播客&pn=100 第四页的url地址: https://tieba.baidu.com/f?kw=传智播客&pn=150 第五页的url地址: https://tieba.baidu.com/f?kw=传智播客&pn=200
-
通过分析发现,每一页的url地址中,都是在参数 pn 的基础上 加 50。第一页的url地址中,是没有pn参数的,那么我们可以尝试一下,第一页的url地址中加上 pn=0,传智播客吧-百度贴吧--传智播客-国内口碑最好的IT培训机构!--中国的软件教育已经坑害了不少软件工程师苗子,传智播客自成立之日起就立志于改变中国的软件教育,目前已经出版IT教程书籍十多本,教学视频几十套, 看看能不能访问成功
-
通过上一步的验证,我们发现第一页的 pn 值为 0
-
那么综上所述,我们可以得出百度贴吧的url地址的规律为:
tb_name:要访问的贴吧的名字 page_num: 当前要访问的页码数 https://tieba.baidu.com/f?kw=tb_name&pn=50 * (page_num - 1)
-
比如我们需要抓取10页的数据,可以先将所有页的url地址构造好,放到一个列表中。
import requests # url地址的模板 base_url = "https://tieba.baidu.com/f?kw={}&pn={}" # 获取要抓取的贴吧的名字 tb_name = input('请输入要抓取的贴吧的名字:') # 获取要抓取的页数 page_num = int(input('请输入要抓取的页数:')) # 构造url地址 url_list = [base_url.format(tb_name, i * 50) for i in range(page_num)] print(url_list)
-
构造好的url地址如下图所示:
-
遍历构造好的url地址,分别对url地址去发送请求,获取到响应数据,再分别将每一页的数据保存到文件中。
# 准备headers中的User-Agent headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36" } # 遍历每一页的url地址,发送请求 获取响应 for url in url_list: response = requests.get(url, headers=headers) # 将获取到的响应的内容,保存到文件中 # 构造文件名 file_name = tb_name + "第{}页.html".format(url_list.index(url) + 1) # 打开文件,将数据保存到文件中 with open(file_name, 'w', encoding='utf-8') as f: f.write(response.content.decode()) print(file_name, '保存成功') # 设置time.sleep() 防止访问速度过快 time.sleep(2)
4.3 完整代码
完整代码如下:
import time
import requests
# url地址的模板
base_url = "https://tieba.baidu.com/f?kw={}&pn={}"
# 获取要抓取的贴吧的名字
tb_name = input('请输入要抓取的贴吧的名字:')
# 获取要抓取的页数
page_num = int(input('请输入要抓取的页数:'))
# 构造url地址
url_list = [base_url.format(tb_name, i * 50) for i in range(page_num)]
# 准备headers中的User-Agent
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
# 遍历每一页的url地址,发送请求 获取响应
for i, url in enumerate(url_list):
response = requests.get(url, headers=headers)
# 将获取到的响应的内容,保存到文件中
# 构造文件名
file_name = tb_name + "第{}页.html".format(i + 1)
# 打开文件,将数据保存到文件中
with open(file_name, 'w', encoding='utf-8') as f:
f.write(response.content.decode())
print(file_name, '保存成功')
# 设置time.sleep() 防止访问速度过快
time.sleep(2)