Python快速入门专业版(五十五):Requests库入门:HTTP请求实战与Header伪装(避坑403反爬)

目录
- 引
- 一、为什么选择Requests库?—— 对比urllib的核心优势
- 二、环境准备:安装Requests库
- 三、Requests核心用法:从发送请求到处理响应
- 1. 发送GET请求:一行代码搞定基础请求
- 示例1:基础GET请求(无参数)
- 示例2:带参数的GET请求(自动拼接URL)
- 2. 响应处理:解析状态码、头信息与响应体
- (1)状态码判断:请求成功的第一关
- (2)响应体解析:文本与二进制的区分
- 3. 解决响应乱码:编码设置的核心技巧
- 乱码产生的原因:
- 解决方法:
- 四、Header伪装:突破403反爬的核心手段
- 1. 爬虫必设的3个核心Header字段
- (1)User-Agent:伪装浏览器身份
- (2)Referer:伪造请求来源
- (3)Cookie:携带登录状态
- 2. 如何获取真实Header?—— 浏览器开发者工具实战
- 3. 案例对比:未设Header vs 设Header的请求结果
- (1)未设置Header的请求(被反爬识别)
- (2)设置Header的请求(成功获取内容)
- 五、实战案例:从API解析到乱码处理
- 案例1:用GET请求获取天气API数据并解析JSON
- 案例2:处理GBK编码网页的乱码问题
- 案例3:用Session保持Cookie登录状态
- 六、避坑指南:Requests使用中的常见问题与解决方案
- 1. 403 Forbidden:被反爬识别的核心原因及解决
- 2. 响应乱码:除了encoding,这些细节也很重要
- 3. 超时设置:避免程序无限等待
- 4. 代理IP:突破IP封禁限制
- 七、总结:Requests是爬虫的“瑞士军刀”
引
在Python爬虫领域,Requests库以其“人类友好”的API设计成为开发者的首选工具。相比Python标准库中的urllib,Requests彻底简化了HTTP请求的处理流程——无需手动拼接URL参数、无需繁琐的编码转换、无需单独处理Cookie,一行代码即可完成从请求发送到响应解析的全流程。更重要的是,它内置了应对基础反爬的能力,通过合理设置请求头(Header)可有效避免403 Forbidden等常见错误。
本文将从Requests库的核心优势出发,系统讲解其安装与基础用法(GET请求、响应处理、编码设置),重点剖析Header字段在反爬中的应用(User-Agent伪装、Referer防盗链、Cookie状态保持),并通过3个实战案例(知乎首页爬取、天气API解析、乱码处理)演示具体用法,帮助开发者快速掌握这一爬虫必备工具,避开403反爬等常见“坑点”。
一、为什么选择Requests库?—— 对比urllib的核心优势
在Requests出现之前,Python开发者主要依赖标准库urllib处理HTTP请求,但urllib的设计过于底层,使用时需要处理大量冗余操作。Requests的出现彻底改变了这一现状,其核心优势可概括为“简洁、强大、人性化”:
| 特性 | urllib | Requests |
|---|---|---|
| URL参数处理 | 需要手动拼接(易出错) | params参数自动拼接(支持字典) |
| 请求头设置 | 需构造Request对象,步骤繁琐 | 直接通过headers参数传入字典 |
| Cookie处理 | 需手动创建CookieJar对象 | 自动保存Cookie(Session更优) |
| 响应编码处理 | 需手动获取charset并解码 | response.text自动解码(可调整) |
| 异常处理 | 需捕获多种底层异常(如URLError) | 统一抛出requests.exceptions异常,便于处理 |
| HTTPS支持 | 需手动配置SSL上下文 | 自动支持HTTPS,无需额外配置 |
一句话总结:Requests让开发者专注于“获取数据”本身,而非HTTP协议的底层细节。这也是它成为爬虫领域事实标准的核心原因。
二、环境准备:安装Requests库
Requests是第三方库,需通过pip安装,安装命令简单直观:
# 基础安装(Python2/Python3通用)
pip install requests# 若系统同时存在Python2和Python3,指定Python3安装
pip3 install requests# 权限不足时(Linux/Mac),添加--user安装到用户目录
pip install requests --user
安装完成后,可在Python环境中验证是否安装成功:
import requests
print(requests.__version__) # 输出当前版本,如2.31.0
若正常输出版本号,说明安装成功。
三、Requests核心用法:从发送请求到处理响应
Requests的核心功能可概括为“发送请求→获取响应→解析数据”,其中GET请求是爬虫最常用的场景(获取网页、接口数据),我们以此为起点展开讲解。
1. 发送GET请求:一行代码搞定基础请求
Requests发送GET请求的基础语法为:
import requestsresponse = requests.get(url, params=None, headers=None)
url:目标资源的URL(如https://www.baidu.com);params:URL查询参数(字典类型,自动拼接为?key1=value1&key2=value2);headers:请求头(字典类型,用于设置User-Agent、Cookie等)。
示例1:基础GET请求(无参数)
# 发送GET请求获取百度首页
response = requests.get("https://www.baidu.com")
print("状态码:", response.status_code) # 输出状态码(200表示成功)
print("响应体前100字符:", response.text[:100]) # 输出HTML前100字符
示例2:带参数的GET请求(自动拼接URL)
爬取“豆瓣电影TOP250”第一页数据(URL为https://movie.douban.com/top250?start=0&filter=),通过params参数传递分页参数:
url = "https://movie.douban.com/top250"
params = {"start": 0, # 起始索引(0表示第一页,25表示第二页,以此类推)"filter": "" # 过滤条件(空表示无过滤)
}
response = requests.get(url, params=params)
print("实际请求的URL:", response.url) # 输出拼接后的完整URL
print("响应状态码:", response.status_code)
输出结果:
实际请求的URL: https://movie.douban.com/top250?start=0&filter=
响应状态码: 200
可以看到,params参数自动将字典转换为URL查询字符串,避免了手动拼接可能出现的编码错误(如中文、特殊字符的URL编码)。
2. 响应处理:解析状态码、头信息与响应体
requests.get()返回的response对象包含了服务器响应的所有信息,掌握其核心属性是解析数据的关键:
| 属性/方法 | 作用描述 | 爬虫常用场景 |
|---|---|---|
response.status_code | 获取响应状态码(如200、403、404) | 判断请求是否成功(200→解析数据,403→处理反爬) |
response.headers | 获取响应头(字典类型,键名自动转为小写) | 提取Content-Type(判断数据格式)、Set-Cookie(保存Cookie) |
response.text | 按默认编码解析响应体为字符串 | 解析HTML、纯文本等文本类数据 |
response.content | 获取响应体的二进制数据(bytes类型) | 保存图片、视频、PDF等二进制文件 |
response.encoding | 获取/设置响应体的编码方式(如’utf-8’) | 解决文本乱码问题(设置为正确编码) |
response.apparent_encoding | 自动识别响应体的实际编码(基于chardet) | 无法确定编码时,作为encoding的参考 |
response.json() | 将JSON格式的响应体解析为字典/列表 | 解析API返回的JSON数据(如天气接口) |
(1)状态码判断:请求成功的第一关
爬虫中需首先通过status_code判断请求是否成功,常见处理逻辑:
response = requests.get(url)
if response.status_code == 200:print("请求成功,开始解析数据")# 处理响应体(response.text/response.json())
elif response.status_code == 403:print("请求被拒绝,可能被反爬识别")# 尝试修改Header(如User-Agent)
elif response.status_code == 404:print("资源不存在,检查URL是否正确")
else:print(f"请求失败,状态码:{response.status_code}")
(2)响应体解析:文本与二进制的区分
- 文本类数据(HTML、JSON、纯文本):用
response.text或response.json()(仅JSON格式); - 二进制数据(图片、文件):用
response.content,并保存为文件。
示例:保存百度首页的logo图片(URL:https://www.baidu.com/img/bd_logo1.png)
# 发送请求获取图片二进制数据
response = requests.get("https://www.baidu.com/img/bd_logo1.png")
if response.status_code == 200:# 用content获取二进制数据,写入文件with open("baidu_logo.png", "wb") as f:f.write(response.content)print("图片保存成功")
3. 解决响应乱码:编码设置的核心技巧
爬虫中最常见的“坑”之一是响应文本乱码(如中文显示为ä¸Â国),这是由于response.text使用的编码与网页实际编码不一致导致的。解决思路是:通过response.encoding设置正确的编码。
乱码产生的原因:
- 网页HTTP响应头的
Content-Type中声明的编码(如charset=utf-8)与网页实际编码(如GBK)不一致; Requests默认使用响应头声明的编码解析response.text,若声明错误,则导致乱码。
解决方法:
- 用
response.apparent_encoding获取网页实际编码(基于chardet库的自动识别); - 将
response.encoding设置为实际编码,再通过response.text解析。
示例:爬取一个使用GBK编码的网页(如某中文新闻网站)
url = "http://www.example-gbk.com/news" # 假设该网页实际编码为GBK
response = requests.get(url)# 查看默认编码(可能为响应头声明的编码,如'ISO-8859-1',导致乱码)
print("默认编码:", response.encoding) # 输出:ISO-8859-1# 查看自动识别的实际编码
print("实际编码:", response.apparent_encoding) # 输出:GBK# 设置正确编码后解析
response.encoding = response.apparent_encoding
print("正确解析的文本:", response.text[:200]) # 中文正常显示
关键原理:apparent_encoding通过分析文本内容(而非响应头)识别编码,准确率较高,适合解决“声明编码与实际编码不一致”的问题。
四、Header伪装:突破403反爬的核心手段
很多网站会通过检测请求头(Header)识别爬虫程序,若发现请求来自非浏览器(如默认的python-requests/2.31.0),则返回403 Forbidden拒绝访问。此时,通过伪装Header模拟浏览器请求,是突破反爬的基础手段。
1. 爬虫必设的3个核心Header字段
(1)User-Agent:伪装浏览器身份
User-Agent(UA)是最常用的反爬检测字段,用于标识客户端类型。浏览器的UA格式通常包含操作系统、浏览器名称和版本,而Requests的默认UA为python-requests/版本号,极易被识别。
解决方法:从浏览器开发者工具中复制真实的UA,设置到请求头中。
示例:Chrome浏览器的UA(可根据实际浏览器版本调整):
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
(2)Referer:伪造请求来源
Referer字段用于告诉服务器当前请求的来源页面(即“从哪个页面跳转到当前URL”)。部分网站(如图片服务器、视频网站)会通过Referer验证请求是否来自自身域名,若来源不符则拒绝访问(防盗链机制)。
解决方法:若爬取的资源(如图片)有防盗链,设置Referer为目标网站的域名。
示例:爬取某网站的图片,设置Referer为该网站首页:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; ...)","Referer": "https://www.target-site.com/" # 来源设为目标网站
}
(3)Cookie:携带登录状态
Cookie用于保持用户会话状态(如登录信息、购物车数据)。部分网站(如知乎、豆瓣)的内容仅对登录用户可见,未登录用户的请求会返回401 Unauthorized或跳转到登录页。
解决方法:从浏览器登录后复制Cookie,设置到请求头中,模拟登录状态。
示例:携带Cookie访问知乎登录后可见的页面:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; ...)","Cookie": "z_c0=xxx; d_c0=xxx; ..." # 从浏览器复制的Cookie字符串
}
2. 如何获取真实Header?—— 浏览器开发者工具实战
获取浏览器的真实Header步骤(以Chrome为例):
- 打开目标网页(如知乎首页),按
F12打开开发者工具; - 切换到“Network”面板,刷新页面(
F5); - 在左侧请求列表中选择目标请求(如
www.zhihu.com的HTML请求); - 在右侧“Headers”→“Request Headers”中复制所需字段(
User-Agent、Cookie等)。
注意:复制时需保留字段的大小写格式(如User-Agent而非user-agent),虽然Requests会自动处理大小写,但严格遵循格式可减少不必要的麻烦。
3. 案例对比:未设Header vs 设Header的请求结果
以爬取知乎首页(https://www.zhihu.com)为例,对比两种情况的差异:
(1)未设置Header的请求(被反爬识别)
import requestsurl = "https://www.zhihu.com"
response = requests.get(url)
print("状态码:", response.status_code) # 输出:403(被拒绝)
print("响应内容:", response.text[:200]) # 输出反爬提示页面
(2)设置Header的请求(成功获取内容)
import requestsurl = "https://www.zhihu.com"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36","Referer": "https://www.zhihu.com/" # 模拟从知乎自身跳转
}
response = requests.get(url, headers=headers)
print("状态码:", response.status_code) # 输出:200(成功)
print("响应内容前200字符:", response.text[:200]) # 输出知乎首页HTML
结果分析:知乎通过检测User-Agent识别爬虫,未设置时返回403,设置浏览器UA后成功获取内容。这证明Header伪装是突破基础反爬的关键。
五、实战案例:从API解析到乱码处理
案例1:用GET请求获取天气API数据并解析JSON
多数开放API(如天气、股票)返回JSON格式数据,Requests的response.json()方法可直接解析为字典,方便提取字段。
以“和风天气API”(需先注册获取免费API密钥)为例,获取北京的实时天气:
import requests# 1. 配置API参数
url = "https://devapi.qweather.com/v7/weather/now"
params = {"location": "116.4074,39.9042", # 北京的经纬度"key": "你的API密钥" # 替换为实际申请的密钥
}
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; ...)" # 避免被API服务器识别为爬虫
}# 2. 发送GET请求
response = requests.get(url, params=params, headers=headers)# 3. 解析JSON数据
if response.status_code == 200:weather_data = response.json() # 直接解析为字典# 提取关键信息now = weather_data["now"]print(f"北京当前天气:{now['text']},温度:{now['temp']}℃,风力:{now['windDir']}{now['windScale']}级")
else:print(f"API请求失败,状态码:{response.status_code}")
输出结果:
北京当前天气:晴,温度:25℃,风力:南风3级
关键点:API接口通常对请求频率有限制,但对User-Agent的检测较宽松,设置基础UA即可避免被误判为爬虫。
案例2:处理GBK编码网页的乱码问题
某中文新闻网站的HTML页面声明编码为ISO-8859-1,但实际使用GBK编码,直接用response.text会导致乱码,需通过apparent_encoding解决。
import requestsurl = "http://www.example-gbk-news.com/article/123.html" # 假设为GBK编码网页
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; ...)"}response = requests.get(url, headers=headers)# 查看默认编码和实际编码
print("默认编码(响应头声明):", response.encoding) # 输出:ISO-8859-1(错误)
print("自动识别的实际编码:", response.apparent_encoding) # 输出:GBK(正确)# 未设置正确编码时的乱码
print("乱码文本:", response.text[:100]) # 输出:ä¸Â国新Ö共产主義...# 设置正确编码后解析
response.encoding = response.apparent_encoding
print("正确文本:", response.text[:100]) # 输出:中国新闻共产党中央委员会...
原理总结:当网页编码声明错误时,apparent_encoding通过分析文本字节序列识别编码,是解决乱码的“万能钥匙”(准确率约90%以上)。
案例3:用Session保持Cookie登录状态
部分网站需要登录后才能访问资源,单独设置Cookie虽能模拟登录,但当Cookie过期时需重新获取。Requests的Session对象可自动保存服务器返回的Cookie,维持会话状态,适合多步操作(如登录→访问个人中心)。
以模拟登录某论坛为例(假设登录接口为/login,个人中心为/profile):
import requests# 1. 创建Session对象(自动保存Cookie)
session = requests.Session()
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; ...)"}# 2. 发送登录请求(表单数据)
login_url = "https://www.example-forum.com/login"
login_data = {"username": "your_username","password": "your_password"
}
# 发送POST请求提交登录表单(Session会自动保存Cookie)
response = session.post(login_url, data=login_data, headers=headers)
if response.status_code == 200:print("登录请求发送成功")# 3. 访问个人中心(Session自动携带登录Cookie)
profile_url = "https://www.example-forum.com/profile"
response = session.get(profile_url, headers=headers)
print("个人中心状态码:", response.status_code) # 输出200表示登录成功
print("个人中心内容前200字符:", response.text[:200])
优势:Session不仅自动处理Cookie,还会复用TCP连接,提升多请求的效率,是爬虫处理登录状态的首选方式。
六、避坑指南:Requests使用中的常见问题与解决方案
1. 403 Forbidden:被反爬识别的核心原因及解决
- 原因1:
User-Agent为默认的python-requests→ 解决方案:设置浏览器UA; - 原因2:缺少关键Header(如
Referer、Accept) → 解决方案:从浏览器复制完整Header; - 原因3:IP被封禁 → 解决方案:使用代理IP(
proxies参数); - 排查方法:用
print(response.text)查看反爬页面提示(如“您的请求被视为爬虫”),针对性调整。
2. 响应乱码:除了encoding,这些细节也很重要
- 若
apparent_encoding识别错误(如将GB2312识别为GBK),可手动指定编码(如response.encoding = "GB2312"); - 对于特殊编码(如
ISO-8859-1),直接用response.content.decode("gbk")解码,避免text属性的自动处理; - 保存文本时指定编码(如
with open("page.html", "w", encoding="utf-8") as f),防止写入文件时乱码。
3. 超时设置:避免程序无限等待
网络不稳定时,请求可能无限阻塞,需设置超时时间:
# 设置超时(连接超时3秒,读取超时7秒)
try:response = requests.get(url, timeout=(3, 7))
except requests.exceptions.Timeout:print("请求超时,可重试")
4. 代理IP:突破IP封禁限制
当本地IP被网站封禁时,需使用代理IP,通过proxies参数设置:
proxies = {"http": "http://123.45.67.89:8080", # HTTP代理"https": "https://123.45.67.89:8080" # HTTPS代理
}
response = requests.get(url, proxies=proxies, headers=headers)
七、总结:Requests是爬虫的“瑞士军刀”
Requests库以其简洁的API设计、强大的功能和人性化的交互,成为Python爬虫的必备工具。掌握它的核心用法(GET请求发送、响应解析、编码处理)是入门的基础,而理解Header伪装、Session会话管理等技巧,则是突破基础反爬、实现稳定爬取的关键。
本文的核心要点可概括为:
- 基础用法:
requests.get()发送请求,response.text/json()解析数据,params自动处理URL参数; - 反爬核心:通过
User-Agent伪装浏览器,Referer处理防盗链,Cookie/Session维持登录状态; - 避坑技巧:用
apparent_encoding解决乱码,设置超时避免阻塞,代理IP突破IP封禁。
在实际爬虫开发中,建议结合浏览器开发者工具分析真实请求,模仿浏览器的Header和参数格式,同时根据网站的反爬策略灵活调整(如动态更新UA、轮换代理)。记住:爬虫的本质是“模拟浏览器行为”,Requests则是实现这一目标的最佳工具。
