🔥本期内容已收录至专栏《Python爬虫实战》,持续完善知识体系与项目实战,建议先订阅收藏,后续查阅更方便~持续更新中!!

全文目录:
-
-
- [🌟 开篇语](#🌟 开篇语)
- [📌 上期回顾](#📌 上期回顾)
- [🎯 本节目标](#🎯 本节目标)
- [一、HTTP 请求头详解](#一、HTTP 请求头详解)
-
- [1.1 为什么需要设置请求头?](#1.1 为什么需要设置请求头?)
- [1.2 常用请求头字段详解](#1.2 常用请求头字段详解)
- [1.3 真实浏览器的请求头](#1.3 真实浏览器的请求头)
- 二、User-Agent:第一道防线
-
- [2.1 常见的 User-Agent](#2.1 常见的 User-Agent)
- [2.2 随机 User-Agent(避免特征识别)](#2.2 随机 User-Agent(避免特征识别))
- [2.3 从浏览器复制 User-Agent](#2.3 从浏览器复制 User-Agent)
- 三、Session:管理会话状态
-
- [3.1 为什么需要 Session?](#3.1 为什么需要 Session?)
- [3.2 Session 基本用法](#3.2 Session 基本用法)
- [3.3 Session 封装类(推荐)](#3.3 Session 封装类(推荐))
- 四、处理需要登录的网站(合规方式)
-
- [4.1 合规声明](#4.1 合规声明)
- [4.2 方法1:手动登录后复制 Cookie](#4.2 方法1:手动登录后复制 Cookie)
- [4.3 方法2:通过表单登录(适用于简单网站)](#4.3 方法2:通过表单登录(适用于简单网站))
- [4.4 验证登录状态](#4.4 验证登录状态)
- 五、常见反爬机制与应对
-
- [5.1 User-Agent 检测](#5.1 User-Agent 检测)
- [5.2 Referer 检测](#5.2 Referer 检测)
- [5.3 请求频率限制](#5.3 请求频率限制)
- [5.4 Cookie/Session 验证](#5.4 Cookie/Session 验证)
- 六、本节小结
- 七、课后作业(必做,验收进入下一节)
-
- [任务1:完善 SmartSession](#任务1:完善 SmartSession)
- [任务2:测试 Session 的 Cookie 持久化](#任务2:测试 Session 的 Cookie 持久化)
- 任务3:实战练习
- [🔮 下期预告](#🔮 下期预告)
- 🌟文末
-
- [📌 专栏持续更新中|建议收藏 + 订阅](#📌 专栏持续更新中|建议收藏 + 订阅)
- [✅ 互动征集](#✅ 互动征集)
-
🌟 开篇语
哈喽,各位小伙伴们你们好呀~我是【喵手】。
运营社区: C站 / 掘金 / 腾讯云 / 阿里云 / 华为云 / 51CTO
欢迎大家常来逛逛,一起学习,一起进步~🌟
我长期专注 Python 爬虫工程化实战 ,主理专栏 👉 《Python爬虫实战》:从采集策略 到反爬对抗 ,从数据清洗 到分布式调度 ,持续输出可复用的方法论与可落地案例。内容主打一个"能跑、能用、能扩展 ",让数据价值真正做到------抓得到、洗得净、用得上。
📌 专栏食用指南(建议收藏)
- ✅ 入门基础:环境搭建 / 请求与解析 / 数据落库
- ✅ 进阶提升:登录鉴权 / 动态渲染 / 反爬对抗
- ✅ 工程实战:异步并发 / 分布式调度 / 监控与容错
- ✅ 项目落地:数据治理 / 可视化分析 / 场景化应用
📣 专栏推广时间 :如果你想系统学爬虫,而不是碎片化东拼西凑,欢迎订阅/关注专栏《Python爬虫实战》
订阅后更新会优先推送,按目录学习更高效~
📌 上期回顾
在上一节《你的第一个爬虫:抓取页面并保存 HTML》中,我们编写了第一个爬虫,成功抓取并保存了网页 HTML。你已经掌握了 requests 的基本用法和文件保存规范。
但现实中,很多网站会检测访问者的身份。如果请求过于"简陋",服务器会认为你是机器人而拒绝访问。这一节,我们将学习如何合理地伪装请求,让爬虫更像真实用户。
重要提醒:本节教授的是合规的请求优化技术,不涉及破解、盗号等违法行为!
🎯 本节目标
通过本节学习,你将能够:
- 理解 HTTP 请求头的作用和常用字段
- 设置完整的 User-Agent、Referer 等请求头
- 使用 Session 对象管理会话和 Cookie
- 处理需要登录的场景(合规方式)
- 识别和避免常见的反爬机制
- 交付验收:编写 Session 版请求器,支持 Cookie 持久化
一、HTTP 请求头详解
1.1 为什么需要设置请求头?
默认请求的问题:
python
import requests
# ❌ 最简单的请求
response = requests.get("https://example.com/")
# 实际发送的请求头(非常简陋)
"""
GET / HTTP/1.1
Host: example.com
User-Agent: python-requests/2.31.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
"""
服务器视角:
- 看到
User-Agent: python-requests/2.31.0→ 这是爬虫! - 缺少
Referer→ 不是从网站内部跳转来的 - 缺少浏览器特有的请求头 → 可疑!
结果:很多网站会直接返回 403 Forbidden 或空白页面。
1.2 常用请求头字段详解
| 字段 | 作用 | 示例值 |
|---|---|---|
| User-Agent | 标识客户端类型 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) |
| Referer | 来源页面URL | https://example.com/list |
| Accept | 可接受的内容类型 | text/html,application/json |
| Accept-Language | 可接受的语言 | zh-CN,zh;q=0.9,en;q=0.8 |
| Accept-Encoding | 支持的编码 | gzip, deflate, br |
| Cookie | 会话凭证 | session_id=abc123; token=xyz |
| Host | 目标主机 | www.example.com |
| Connection | 连接方式 | keep-alive |
1.3 真实浏览器的请求头
python
# ✅ 模拟 Chrome 浏览器的完整请求头
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',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,'
'image/webp,image/apng,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Referer': 'https://www.google.com/',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'cross-site',
'Cache-Control': 'max-age=0'
}
response = requests.get(url, headers=headers)
二、User-Agent:第一道防线
2.1 常见的 User-Agent
python
# Windows Chrome
UA_CHROME_WIN = (
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
)
# Mac Safari
UA_SAFARI_MAC = (
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 '
'(KHTML, like Gecko) Version/17.2 Safari/605.1.15'
)
# iPhone Safari
UA_IPHONE = (
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 '
'(KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1'
)
# Android Chrome
UA_ANDROID = (
'Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/120.0.6099.144 Mobile Safari/537.36'
)
2.2 随机 User-Agent(避免特征识别)
python
import random
class UserAgentPool:
"""User-Agent 池"""
AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15',
]
@classmethod
def random(cls):
"""返回随机 User-Agent"""
return random.choice(cls.AGENTS)
# 使用
headers = {'User-Agent': UserAgentPool.random()}
response = requests.get(url, headers=headers)
2.3 从浏览器复制 User-Agent
步骤:
- 打开浏览器开发者工具(F12)
- 切换到 Network 标签
- 刷新页面,点击任意请求
- 在 Headers 部分找到
User-Agent - 复制完整字符串
python
# 从浏览器复制的真实 User-Agent
MY_USER_AGENT = "粘贴你从浏览器复制的内容"
三、Session:管理会话状态
3.1 为什么需要 Session?
问题场景:
python
# ❌ 每次请求都是独立的,Cookie 不会保留
response1 = requests.get("https://example.com/login", data={...})
response2 = requests.get("https://example.com/profile") # 失败!未登录
# 原因:response1 返回的 Cookie 没有在 response2 中携带
Session 的作用:
- ✅ 自动保存和发送 Cookie
- ✅ 跨请求保持连接(性能更好)
- ✅ 统一管理请求头
3.2 Session 基本用法
python
import requests
# 创建 Session 对象
session = requests.Session()
# 设置统一的请求头
session.headers.update({
'User-Agent': UserAgentPool.random(),
'Accept-Language': 'zh-CN,zh;q=0.9',
})
# 第一次请求
response1 = session.get("https://httpbin.org/cookies/set?session_id=abc123")
print("Set-Cookie:", response1.headers.get('Set-Cookie'))
# 第二次请求(自动携带上次的 Cookie)
response2 = session.get("https://httpbin.org/cookies")
print("发送的 Cookie:", response2.json())
# 输出:{"cookies": {"session_id": "abc123"}}
3.3 Session 封装类(推荐)
python
import requests
import time
import json
import os
class SmartSession:
"""智能 Session 管理器"""
def __init__(self, cookie_file=None):
"""
初始化
Args:
cookie_file: Cookie 持久化文件路径
"""
self.session = requests.Session()
self.cookie_file = cookie_file
# 设置默认请求头
self.session.headers.update({
'User-Agent': UserAgentPool.random(),
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
})
# 加载已保存的 Cookie
if cookie_file and os.path.exists(cookie_file):
self.load_cookies()
def get(self, url, **kwargs):
"""GET 请求(带重试)"""
return self._request('GET', url, **kwargs)
def post(self, url, **kwargs):
"""POST 请求(带重试)"""
return self._request('POST', url, **kwargs)
def _request(self, method, url, max_retries=3, retry_delay=2, **kwargs):
"""
发起请求(内部方法)
Args:
method: 请求方法
url: 目标URL
max_retries: 最大重试次数
retry_delay: 重试延迟(秒)
**kwargs: 传递给 requests 的参数
"""
for attempt in range(max_retries):
try:
if method == 'GET':
response = self.session.get(url, timeout=10, **kwargs)
else:
response = self.session.post(url, timeout=10, **kwargs)
response.raise_for_status()
return response
except requests.exceptions.RequestException as e:
print(f"❌ 请求失败 (尝试 {attempt+1}/{max_retries}): {e}")
if attempt < max_retries - 1:
time.sleep(retry_delay)
else:
raise
def save_cookies(self):
"""保存 Cookie 到文件"""
if not self.cookie_file:
return
# 将 Cookie 转为字典
cookies_dict = requests.utils.dict_from_cookiejar(self.session.cookies)
with open(self.cookie_file, 'w') as f:
json.dump(cookies_dict, f, indent=2)
print(f"💾 Cookie 已保存到: {self.cookie_file}")
def load_cookies(self):
"""从文件加载 Cookie"""
if not os.path.exists(self.cookie_file):
return
with open(self.cookie_file, 'r') as f:
cookies_dict = json.load(f)
# 将字典转为 Cookie
for name, value in cookies_dict.items():
self.session.cookies.set(name, value)
print(f"📂 Cookie 已加载: {self.cookie_file}")
def set_cookie(self, name, value, domain=None):
"""手动设置 Cookie"""
self.session.cookies.set(name, value, domain=domain)
def get_cookies(self):
"""获取当前所有 Cookie"""
return requests.utils.dict_from_cookiejar(self.session.cookies)
def close(self):
"""关闭 Session"""
self.session.close()
# ========== 使用示例 ==========
# 示例1:基本用法
session = SmartSession()
response = session.get("https://httpbin.org/get")
print(response.json())
# 示例2:Cookie 持久化
session = SmartSession(cookie_file='cookies.json')
# 第一次访问(会设置 Cookie)
response1 = session.get("https://httpbin.org/cookies/set?token=abc123")
# 保存 Cookie
session.save_cookies()
# ===== 重启程序 =====
# 加载之前保存的 Cookie
session2 = SmartSession(cookie_file='cookies.json')
response2 = session2.get("https://httpbin.org/cookies")
print("恢复的 Cookie:", response2.json())
四、处理需要登录的网站(合规方式)
4.1 合规声明
⚠️ 重要:本节只教授合规的登录方式:
- ✅ 使用自己的账号登录
- ✅ 采集自己有权限访问的数据
- ❌ 禁止破解他人账号
- ❌ 禁止绕过付费墙
- ❌ 禁止访问未授权数据
4.2 方法1:手动登录后复制 Cookie
步骤:
- 用浏览器正常登录网站
- 打开开发者工具(F12)→ Application/存储
- 找到 Cookies,复制所有 Cookie
- 在代码中手动设置
python
session = SmartSession()
# 手动设置从浏览器复制的 Cookie
cookies = {
'session_id': 'abc123def456',
'user_token': 'xyz789',
'user_id': '12345',
}
for name, value in cookies.items():
session.set_cookie(name, value)
# 现在可以访问需要登录的页面
response = session.get("https://example.com/profile")
4.3 方法2:通过表单登录(适用于简单网站)
python
def login(session, login_url, username, password):
"""
表单登录
Args:
session: SmartSession 对象
login_url: 登录接口URL
username: 用户名
password: 密码
Returns:
bool: 是否登录成功
"""
# 登录表单数据
data = {
'username': username,
'password': password,
# 'csrf_token': '...', # 如果需要CSRF令牌
}
try:
response = session.post(login_url, data=data)
# 检查登录是否成功(根据实际情况调整)
if '登录成功' in response.text or response.status_code == 200:
print("✅ 登录成功")
# 保存 Cookie 以便下次使用
session.save_cookies()
return True
else:
print("❌ 登录失败")
return False
except Exception as e:
print(f"❌ 登录异常: {e}")
return False
# 使用示例
session = SmartSession(cookie_file='login_cookies.json')
# 首次登录
if not os.path.exists('login_cookies.json'):
login(session,
login_url="https://example.com/login",
username="your_username",
password="your_password")
# 后续使用已保存的 Cookie
response = session.get("https://example.com/data")
4.4 验证登录状态
python
def check_login_status(session, check_url):
"""
检查是否已登录
Args:
session: SmartSession 对象
check_url: 检查登录状态的URL(如个人主页)
Returns:
bool: 是否已登录
"""
try:
response = session.get(check_url)
# 根据响应内容判断(需根据实际网站调整)
if '退出登录' in response.text or '个人中心' in response.text:
print("✅ 已登录")
return True
else:
print("❌ 未登录或登录已过期")
return False
except Exception as e:
print(f"❌ 检查失败: {e}")
return False
五、常见反爬机制与应对
5.1 User-Agent 检测
检测方式:服务器检查 User-Agent 是否为常见爬虫
应对:
python
# ✅ 使用随机 User-Agent
headers = {'User-Agent': UserAgentPool.random()}
5.2 Referer 检测
检测方式:检查请求是否来自站内跳转
应对:
python
# 示例:访问详情页时,设置 Referer 为列表页
headers = {
'Referer': 'https://example.com/news/list'
}
response = session.get('https://example.com/news/detail/123', headers=headers)
5.3 请求频率限制
检测方式:同一 IP 短时间内请求过多
应对:
python
import time
urls = [...]
for url in urls:
response = session.get(url)
# 处理数据...
# 延迟 2-5 秒(礼貌爬取)
time.sleep(random.uniform(2, 5))
5.4 Cookie/Session 验证
检测方式:检查 Cookie 是否存在或有效
应对:
python
# 使用 Session 自动管理 Cookie
session = SmartSession(cookie_file='cookies.json')
六、本节小结
本节我们学习了请求伪装的核心技能:
✅ 请求头设置 :User-Agent、Referer、Accept 等字段
✅ Session 管理 :自动保存和发送 Cookie
✅ Cookie 持久化 :保存到文件,下次自动加载
✅ 登录处理 :合规的登录方式和状态检查
✅ 反爬应对:识别常见机制并合理应对
核心原则:
- 模拟真实浏览器,但不伪造身份
- 使用自己的账号,不访问未授权数据
- 控制请求频率,礼貌爬取
- Cookie 敏感信息要妥善保管
七、课后作业(必做,验收进入下一节)
任务1:完善 SmartSession
为 SmartSession 类添加以下方法:
python
def set_proxy(self, proxy_url):
"""设置代理(如有需要)"""
pass
def clear_cookies(self):
"""清除所有 Cookie"""
pass
def export_cookies_to_browser_format(self, output_file):
"""导出为浏览器可导入的格式(Netscape format)"""
pass
任务2:测试 Session 的 Cookie 持久化
编写脚本:
- 访问 httpbin.org/cookies/set 设置 Cookie
- 保存 Cookie 到文件
- 重新创建 Session 并加载 Cookie
- 验证 Cookie 是否成功恢复
任务3:实战练习
选择一个需要简单登录的网站(建议用测试网站或自己的账号):
- 手动登录后复制 Cookie
- 在代码中设置 Cookie
- 访问需要登录才能看到的页面
- 验证是否成功获取数据
验收方式:在留言区提交:
- 扩展功能的代码
- Cookie 持久化测试的运行截图
- 实战练习的结果(注意隐藏敏感信息)
- 学习心得
🔮 下期预告
下一节《稳定性第一课:超时、重试、退避》,我们将学习:
- 为什么超时设置是必需的
- 实现智能重试机制(指数退避)
- 区分哪些错误该重试,哪些不该
- 失败日志的设计规范
- 编写 HttpClient v1(生产级请求器)
预习建议 :
思考:当一个请求失败时,应该立即重试、还是等待一段时间?等待多久合适?
💬 Session 是稳定爬虫的基石!掌握它,事半功倍!
记住:伪装不是欺骗,而是让你的爬虫更"礼貌"。合规合法地采集数据,是工程师的职业操守。
🌟文末
好啦~以上就是本期 《Python爬虫实战》的全部内容啦!如果你在实践过程中遇到任何疑问,欢迎在评论区留言交流,我看到都会尽量回复~咱们下期见!
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦~
三连就是对我写作道路上最好的鼓励与支持! ❤️🔥
📌 专栏持续更新中|建议收藏 + 订阅
专栏 👉 《Python爬虫实战》,我会按照"入门 → 进阶 → 工程化 → 项目落地"的路线持续更新,争取让每一篇都做到:
✅ 讲得清楚(原理)|✅ 跑得起来(代码)|✅ 用得上(场景)|✅ 扛得住(工程化)
📣 想系统提升的小伙伴:强烈建议先订阅专栏,再按目录顺序学习,效率会高很多~

✅ 互动征集
想让我把【某站点/某反爬/某验证码/某分布式方案】写成专栏实战?
评论区留言告诉我你的需求,我会优先安排更新 ✅
⭐️ 若喜欢我,就请关注我叭~(更新不迷路)
⭐️ 若对你有用,就请点赞支持一下叭~(给我一点点动力)
⭐️ 若有疑问,就请评论留言告诉我叭~(我会补坑 & 更新迭代)
免责声明:本文仅用于学习与技术研究,请在合法合规、遵守站点规则与 Robots 协议的前提下使用相关技术。严禁将技术用于任何非法用途或侵害他人权益的行为。