Skip to content

爬虫进阶 - 突破 Web 反爬(课程导学)

被反爬搞崩溃了N次还没搞定?问题出在这——你根本没看清对手的全貌。

我是怕浪猫,一个在爬虫坑里摸爬滚打多年的老司机。今天这期内容,我要带你重新认识反爬这件事,不是教你写个 requests 请求就完事,而是从工程师视角,系统性拆解 Web 端反爬的全貌。从请求头检测到浏览器指纹,从代理池搭建到分布式架构,十一章内容,带你从入门到精通。

在正式开始之前,我想先聊聊为什么我要写这个系列。网上爬虫教程多如牛毛,但大部分都停留在"如何用 requests 抓数据"的层面。真正到了生产环境,你会发现数据抓取只是冰山一角,真正耗时耗力的是跟反爬系统斗智斗勇。这个系列的目标就是填补这个空白,把我在实战中积累的经验和踩过的坑都分享出来,让你少走弯路。

1.1 课程导学

爬虫进阶之破解 Web 端反爬技术

很多初学者问我:"为什么我的爬虫刚跑两页就被封了?"、"为什么明明浏览器能打开网页,代码却拿到空数据?"——答案往往藏在网站的"反爬机制"里。

爬虫工程师的真实工作场景是这样的:你写好代码,满怀信心地运行,然后:

python
import requests

url = "https://example.com/api/data"
response = requests.get(url)
print(response.status_code)  # 403
print(response.text)  # {"error": "请求频率过高"}

四十三个错误码、四二九频率限制、验证码挑战、数据加密、空响应……这些就是反爬的冰山一角。

每一个错误码背后都对应着一种反爬策略。四十百三通常意味着你的请求被直接拒绝了,可能是因为请求头不完整或者缺少必要的认证信息。四二九表示你请求太频繁了,需要降低频率或者更换 IP。有些网站还会返回二零零状态码但响应体是空的,这种"软封禁"更难察觉,你的代码以为请求成功了,实际上什么数据都没拿到。

爬虫的本质是模拟人的行为,反爬的本质是识别机器行为。这场猫鼠游戏,从来没有终点。

这门课程不讲基础语法,只讲实战中真正会遇到的"拦路虎"。从请求头检测到浏览器指纹,从 IP 封禁到登录态验证,从 JavaScript 逆向到分布式架构,我们一个一个拆解。

很多教程教你的爬虫流程是这样的:

requests.get(url) → 解析HTML → 存入数据库

但真实的生产级爬虫流程远比这复杂:

需求分析 → 目标网站分析 → 反爬策略识别

环境搭建 → 代理池准备 → 指纹库构建

编写爬虫 → 异常处理 → 重试机制

数据清洗 → 去重存储 → 质量校验

监控告警 → 日志分析 → 持续维护

每一个环节都有大量细节需要处理。比如需求分析阶段,你需要明确采集频率要求、数据量预估、数据格式要求、更新策略等。目标网站分析阶段,你需要搞清楚目标网站的技术栈、接口结构、反爬措施、数据更新频率等。反爬策略识别阶段,你需要判断目标网站使用了哪些反爬手段,是简单的请求头检测还是复杂的浏览器指纹,是频率限制还是行为分析。

编写爬虫阶段,你需要考虑代码的健壮性、异常处理、日志记录、重试机制等。数据清洗阶段,你需要处理脏数据、去除重复项、格式化字段。监控告警阶段,你需要实时关注爬虫的运行状态,一旦出现异常能及时发现和处理。每一个环节都需要认真对待,任何一个环节的疏忽都可能导致整个系统崩溃。

特别是在生产环境中,爬虫系统通常需要长期稳定运行。这就要求你的代码不仅要能跑,还要能应对各种突发情况:网络抖动、目标网站改版、反爬升级、代理失效等。好的爬虫工程师写出的代码,不是那些精巧的单行代码,而是那些能经受住时间考验的健壮代码。

写出能跑的爬虫只需要一天,写出能稳定跑一年的爬虫需要一年。

课程整体架构与学习路径图

整个系列课程分为十一章,逻辑上遵循"先理解原理,再动手实战"的原则。下面是完整的学习路径:

第1章 爬虫进阶 - 突破 Web 反爬(导学)        ← 你在这里
第2章 HTTP 网络基础 - 理解数据传输的底层逻辑
第3章 请求头反爬 - 最基础也最容易被忽视
第4章 IP 代理池实战 - 突破频率限制的核心武器
第5章 验证码识别系统 - 从简单图形到滑动验证
第6章 Cookie 与登录态管理 - 持久化会话的艺术
第7章 JavaScript 逆向基础 - 抓取动态数据的必经之路
第8章 浏览器指纹对抗 - 最隐蔽的反爬手段
第9章 分布式爬虫架构 - 规模化爬取的工程实践
第10章 数据加密与解密实战 - 保护数据,破解数据
第11章 综合案例与总结 - 学以致用

学习路径可以总结为一个公式:

扎实基础 → 理解反爬 → 掌握工具 → 实战演练 → 总结复盘

这个学习顺序不是随意排列的,而是有内在逻辑的。你在理解了 HTTP 协议之后,才能理解请求头为什么能用来反爬;理解了请求头之后,才能理解为什么单靠改 User-Agent 不够用;理解了 IP 封禁之后,才能理解代理池的设计思路;理解了验证码之后,才能设计合理的重试和降级策略。每一章都是前一章的自然延伸,跳着看容易产生知识盲区。

比如我见过有人直接跳到 JavaScript 逆向章节,结果发现自己在分析加密参数时,连请求是怎么发出去的都搞不清楚。也有人跳过了 IP 代理池章节,等到真正需要大规模采集时才发现自己的爬虫跑了十分钟就被封了。知识的连贯性在这个领域尤为重要,因为反爬是一个系统性工程,你需要理解整个体系才能有效应对。

建议你在学习每一章的时候,都先通读一遍了解全貌,再逐节细读深入理解,最后动手实践巩固所学。每章的代码示例都是经过验证的,你可以直接运行,但更好的方式是理解原理后自己重写一遍,这样学到的才是真正属于你的知识。

没有速成的爬虫工程师,只有不断踩坑再爬起来的实战派。怕浪猫踩过的坑,希望你能少踩几个。

爬虫工程师能力模型与成长路径

一个成熟的爬虫工程师需要具备三方面的核心能力,我把它们分为基础层、进阶层和高级层。这个分层不是绝对的,但可以作为你规划学习路径的参考。

技术能力矩阵

┌─────────────────────────────────────────────────────┐
│                    爬虫工程师能力模型                 │
├─────────────────────────────────────────────────────┤
│  基础层                                              │
│  ├── Python 编程基础                                │
│  ├── HTTP/HTTPS 协议理解                            │
│  ├── HTML/CSS/JavaScript 前端知识                   │
│  └── 数据结构与算法                                 │
├─────────────────────────────────────────────────────┤
│  进阶层                                              │
│  ├── 网页解析(XPath/CSS选择器/正则)               │
│  ├── 异步并发(asyncio/aiohttp)                    │
│  ├── 数据存储(MySQL/MongoDB/Redis)               │
│  └── 代理池与验证码处理                             │
├─────────────────────────────────────────────────────┤
│  高级层                                              │
│  ├── JavaScript 逆向工程                           │
│  ├── 浏览器自动化(Playwright/Puppeteer)          │
│  ├── 分布式架构设计                                 │
│  └── 反爬策略分析与对抗                             │
└─────────────────────────────────────────────────────┘

很多初学者一上来就想学 JavaScript 逆向,这就像还没学会走就想跑。正确的学习顺序是:先打好 Python 和 HTTP 基础,再掌握网页解析和并发技术,最后才进入逆向和架构设计。每一层的能力都需要时间沉淀,不能跳级。我见过太多人基础还没打牢就去搞 JavaScript 逆向,结果遇到一个稍微复杂的加密逻辑就懵了。也见过有人连 HTTP 协议都没搞懂就去搭分布式爬虫,最后整个集群都在做无用功。基础不牢,地动山摇,这句话在爬虫领域同样适用。

基础层的能力决定了你能不能写出能用的爬虫,进阶层的能力决定了你能不能写出好用的爬虫,高级层的能力决定了你能不能解决别人解决不了的问题。每一层都是下一层的根基,跳过基础直接学高级内容,就像在沙滩上建高楼,看着挺高,一个浪打过来就塌了。

爬虫工程师的护城河不是会写代码,而是能处理别人处理不了的反爬场景。

成长路径时间线

入门期(1-3个月)
├── 会用 requests + BeautifulSoup 写简单爬虫
├── 了解 HTTP 请求基本流程
├── 能处理静态页面数据抓取
└── 学会使用 Chrome DevTools 分析请求

进阶期(3-6个月)
├── 掌握异步并发提升效率
├── 学会使用代理池规避封禁
├── 能处理登录态和简单验证码
├── 开始接触动态页面渲染
└── 理解常见反爬策略

高级期(6-12个月)
├── 熟练进行 JavaScript 逆向
├── 能对抗浏览器指纹检测
├── 设计分布式爬虫架构
├── 具备反爬策略分析能力
└── 能独立设计完整数据采集系统

专家期(12个月以上)
├── 全栈能力(爬虫+数据分析+后端)
├── 能独立设计和实现复杂爬虫系统
├── 持续关注反爬技术演进
├── 具备架构优化和性能调优经验
└── 能带领团队完成大型数据采集项目

入门期的重点是"能用",你需要掌握 Python 基础语法、requests 库的使用、简单的网页解析方法。这个阶段不要追求完美,先把数据抓下来再说。很多人在这个阶段卡太久,总想把代码写得优雅,其实没必要,能跑就行,先建立成就感。

进阶期的重点是"好用",你需要学会异步并发提升效率、使用代理池规避封禁、处理登录态和验证码。这个阶段开始接触真实场景中的反爬问题,也是大多数爬虫工程师最痛苦的阶段,因为你会发现之前学的基础知识远远不够用。

高级期的重点是"能打",你需要深入 JavaScript 逆向、浏览器指纹对抗、分布式架构设计。这个阶段你已经可以独立完成复杂的数据采集项目了,也是你真正开始建立技术壁垒的阶段。

专家期的重点是"能带",你需要具备全栈视野、架构设计能力、团队协作能力。这个阶段你不仅自己能做,还能带领团队高效完成大型项目。技术能力已经不再是瓶颈,更重要的在于项目管理、技术选型和风险控制。

1.2 爬虫工程师学习建议

爬虫重点学习方向梳理

很多人问我爬虫到底该学什么,感觉东西太多了无从下手。我整理了一个"爬虫学习四象限",帮你分清主次:

                    重要且紧急
                    ┌─────────────────────────────┐
                    │  HTTP协议理解                │
                    │  请求头反爬对抗              │
                    │  IP代理池搭建                │
                    │  常见验证码识别              │
                    │  数据解析与存储              │
                    └─────────────────────────────┘
         重要不紧急│                             │紧急不重要
                    ┌─────────────────────────────┐
                    │  JavaScript 逆向             │      │
                    │  浏览器指纹对抗              │      │
                    │  分布式架构设计              │      │
                    │  数据加密解密                │      │
                    │  AST 抽象语法树分析          │      │
                    └─────────────────────────────┘
                    │                             │
                    └─────────────────────────────┘
                    不重要不紧急

先集中精力搞定"重要且紧急"的部分,这部分能在短期内显著提升你的实战能力。等基础扎实了,再逐步攻克"重要不紧急"的高级话题。

在学习过程中,我发现一个普遍的误区:很多人喜欢追求最新的、最酷的技术,比如上来就想学抽象语法树反混淆、WebAssembly 逆向这些高级话题。但实际工作中,百分之八十的反爬场景用基础技术就能解决。把基础打牢,比追逐新技术更有价值。

另一个建议是:学习爬虫最好的方式就是实战。光看书不动手是学不会爬虫的。你可以给自己设定一些小项目,比如爬取一个新闻网站的所有文章、监控某个商品的价格变化、采集某个论坛的帖子数据。在实际项目中遇到的问题会比任何教程都更有教育意义。

方向一:HTTP 协议深入理解

HTTP 是爬虫的基石,不理解 HTTP 就永远写不好爬虫。你需要掌握的核心知识点包括:请求方法的使用场景和区别、请求头的各个字段含义及其反爬应用、Cookie 和 Session 的工作机制、HTTPS 加密原理(对称加密加非对称加密加数字证书)、状态码含义及异常处理策略、HTTP/2 与 HTTP/1.1 的差异对爬虫的影响。

一个典型的 HTTP 请求结构:

python
import requests

headers = {
    "User-Agent": "Mozilla/5.0 ...",
    "Accept": "text/html,application/xhtml+xml",
    "Accept-Language": "zh-CN,zh;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "Connection": "keep-alive",
    "Referer": "https://example.com/"
}

cookies = {"session_id": "abc123xyz"}

response = requests.get(
    "https://example.com/api/data",
    headers=headers,
    cookies=cookies,
    timeout=10
)

很多初学者只写了 requests.get(url) 就跑,结果当然被识别为爬虫。HTTP 协议的每个字段都可能成为反爬的检测点。比如 Accept-Language 头,如果你设置了中文环境但请求里没有这个头,服务端就会怀疑你的身份。再比如 Referer 头,如果你直接访问一个深层页面的 URL 却没有 Referer,这在正常浏览中几乎不可能发生。

更深层次的检测还包括请求头的顺序。真实浏览器发送请求时,请求头的顺序是有规律的,比如 User-Agent 通常在前面,Accept 在后面。而 Python 的 requests 库发送的请求头顺序与浏览器不同,有些精细的反爬系统会检查请求头的顺序。这就要求我们在模拟浏览器请求时,不仅要设置正确的字段,还要注意字段的排列顺序。

还有一个容易忽略的细节是 TLS 指纹。不同客户端在建立 HTTPS 连接时,TLS 握手的特征是不同的。Python 的 requests 库使用的 OpenSSL 库在 TLS 握手时暴露的特征与 Chrome 浏览器明显不同,有些反爬系统就是通过 TLS 指纹来识别爬虫的。这部分内容在第二章会有详细讲解。

把 HTTP 协议当作爬虫的"内功心法"来练,招式可以速成,内功没有捷径。

方向二:数据解析技术

三大解析技术各有优劣,实际项目中建议组合使用:

技术优点缺点适用场景
XPath语法强大,轴定位灵活学习成本较高复杂 HTML 结构
CSS选择器前端友好,语法简洁功能相对有限类名/id 定位
正则表达式万能,可处理任意文本可读性差,维护困难非结构化文本

组合使用的典型代码:

python
from lxml import etree
import re

html = etree.HTML(response.text)

# 先用 XPath 定位到大致区域
items = html.xpath('//div[@class="list"]/div[@class="item"]')

for item in items:
    title = item.xpath('.//h2[@class="title"]/text()')[0]
    price_text = item.xpath('.//span/text()')[0]
    price = re.search(r'\d+', price_text).group()

解析技术的选择原则是:能用 XPath 就不用正则,能用 CSS 选择器就不用 XPath。原因很简单,可维护性。正则表达式虽然万能,但写出来的代码三个月后你自己都看不懂。

在实际项目中,数据解析往往是最耗时的环节之一。因为网站的 HTML 结构经常变化,你的解析代码需要不断调整。如果解析逻辑写得太复杂或者太依赖正则,每次网站改版你都要花大量时间去修改。好的解析代码应该是清晰易懂的,即使网站结构变了,也能快速定位需要修改的地方。

另一个值得注意的趋势是越来越多的网站使用动态渲染,也就是说你抓到的 HTML 只是一个空壳,真正的数据是通过 JavaScript 动态加载的。这种情况下,传统的解析方法就不够用了,你需要借助浏览器自动化工具或者直接分析接口请求。这个话题在第七章 JavaScript 逆向中会深入讲解。

方向三:反爬对抗核心技能

反爬技术层出不穷,但核心就这五类。我先给你一个全景图,后面的章节会逐个深入:

反爬技术分类
├── 请求头检测      ← 最基础,通过率约百分之八十
├── IP封禁         ← 最常见,需要代理池
├── 验证码识别      ← 最麻烦,消耗资源多
├── 登录态验证      ← 需要维护Cookie
└── 浏览器指纹      ← 最隐蔽,需要深入研究

反爬和爬虫是猫鼠游戏,没有一劳永逸的方案,只有不断演进的对抗。

方向四:异步并发与性能优化

当你需要采集大量数据时,单线程爬虫效率太低。异步并发是必修课:

python
import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [f"https://example.com/page/{i}" for i in range(100)]
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)

asyncio.run(main())

但并发也不是越高越好,需要考虑目标网站的承受能力和反爬阈值。并发太高不仅可能被封 IP,还可能给目标服务器造成压力,这在法律和道德层面都是不可取的。合理的做法是设置并发上限、添加请求间隔、实现指数退避重试机制。

并发控制的核心是找到"速度"和"隐蔽性"的平衡点。你的爬虫不仅要快,还要"看起来像人"。一个合理的爬虫应该具备以下特征:随机化的请求间隔、自适应的并发调整、智能的限速策略、以及完善的异常处理。这些内容会在第四章和第九章中详细讲解。

关于性能优化,还有一个经常被忽略的点就是连接复用。每次请求都新建 TCP 连接的开销是很大的,使用连接池可以显著提升性能。requests 库的 Session 对象就自带连接池功能, aiohttp 的 ClientSession 也是同理。养成使用 Session 对象的习惯,你的爬虫效率会有明显提升。

爬虫工程师该何去何从?

这是个好问题,也是每个爬虫工程师都会面对的职业选择。我总结了三条主要的发展路径。

路径一:深耕爬虫领域

成为爬虫专家,专注于大规模数据采集系统。这类岗位通常在大厂的数据中台、搜索引擎团队,或者专业的数据服务公司。核心能力要求包括分布式爬虫架构设计、高并发高可用系统实现、复杂反爬对抗经验以及数据质量保障体系。这个方向的天花板很高,大厂的高级爬虫工程师年薪可以达到很可观的水平。

但这条路也有挑战。反爬技术在不断演进,你需要持续学习。今天管用的方案明天可能就失效了。另外,爬虫工程师需要面对的法律风险也比其他岗位更高,你需要对数据合规有清醒的认识。在采集数据之前,一定要仔细阅读目标网站的 robots 协议和用户协议,了解哪些数据可以采、哪些不能采、采集频率有什么限制。合规不仅是对他人的尊重,也是对自己的保护。

路径二:转向数据工程

爬虫只是数据获取的第一步,数据清洗、存储、分析、可视化构成完整的数据链路。很多爬虫工程师会顺势转型为数据工程师。转型路径:

爬虫工程师 → 数据工程师
    ├── 补充数据仓库知识(Hive/Spark SQL)
    ├── 学习 ETL 工具链(Airflow/dbt)
    ├── 掌握大数据处理框架(Spark/Flink)
    └── 强化数据分析能力(SQL/Pandas)

这条路的好处是职业空间更广,数据工程师的岗位需求量大,薪资水平也不错。而且你在爬虫阶段积累的数据处理经验可以直接复用。

路径三:转向后端开发

爬虫本质上是 HTTP 客户端,对协议、并发、数据处理的理解都可以复用到后端开发。转型要点包括补充服务端框架知识(Django/FastAPI/Flask),学习数据库设计与优化,掌握微服务架构,以及强化系统设计能力。

我的建议是:先深挖一个方向,再横向扩展。爬虫技术本身有足够深度,值得深耕两到三年。之后根据兴趣和机会选择横向发展。

技术没有银弹,职业规划也没有标准答案。关键是在一个方向上积累足够深,才有选择的权利。

反爬技术全景图:请求头检测、IP封禁、登录态验证、数据加密、浏览器指纹

这是本章的核心内容。我把反爬技术整理成一个完整的知识图谱,后面的每一章都会深入展开其中的一个或多个主题。

                        Web反爬技术全景图

            ┌─────────────────┼─────────────────┐
            │                 │                 │
        请求层反爬         数据层反爬         行为层反爬
            │                 │                 │
    ┌───────┴───────┐    ┌────┴────┐     ┌──────┴──────┐
    │               │    │         │     │             │
 请求头检测      IP封禁   数据加密  数据混淆  访问频率控制  行为分析
    │               │    │         │     │             │
┌───┴───┐       ┌───┴───┐│         │ ┌───┴───┐     ┌───┴───┐
UA检测  Referer 频率限制   │         │ │阈值限制│     │鼠标轨迹│
Cookie检测 检测  IP黑名单  │         │ └───────┘     │点击频率│
Accept检测    地理限制    │         │               │访问顺序│
语言检测      VPN/代理识别  │         │               │停留时间│
sec-ch-ua                  │         │

请求头检测详解

服务器通过检查 HTTP 请求头判断请求是否来自真实浏览器。这是最基础也最容易被忽视的反爬手段。很多开发者只设置了 User-Agent 就以为万事大吉,殊不知服务端的检测远不止于此。

python
# 典型浏览器请求头
browser_headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9",
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
    "Accept-Encoding": "gzip, deflate, br",
    "Connection": "keep-alive",
    "Referer": "https://www.google.com/",
    "sec-ch-ua": '"Chromium";v="122", "Google Chrome";v="122"',
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": '"macOS"'
}

# 爬虫默认请求头(容易被识别)
crawler_headers = {
    "User-Agent": "python-requests/2.28.0"
}

请求头反爬的核心检测流程:

服务器检测流程:
┌─────────────┐
│ 接收请求    │
└──────┬──────┘


┌─────────────────────────────────┐
│ 检查 User-Agent                 │
│ 是否包含 python、curl、scrapy   │
│ 是否为空或与其它头字段矛盾      │
└──────┬──────────────────────────┘


┌─────────────────────────────────┐
│ 检查 Referer + Cookie           │
│ 来源域名是否合法 / Cookie有效性 │
│ 是否与IP和UA绑定                │
└──────┬──────────────────────────┘


┌─────────────────────────────────┐
│ 检查 sec-ch-ua 客户端提示头     │
│ 是否与UA一致 / 是否缺少应有字段 │
└──────┬──────────────────────────┘


   正常响应 / 拦截响应

很多人觉得改个 User-Agent 就能绕过请求头反爬,其实服务端检测的是请求头的"一致性"——一个 Chrome 的 UA 配一个没有 Accept-Language 的请求,比直接暴露 python-requests 更可疑。

请求头检测的精妙之处在于"交叉验证"。比如你声称使用的是 Chrome 浏览器,那你的请求头里就应该有 Chrome 特有的字段,比如 sec-ch-ua 系列客户端提示头。如果缺少这些字段,服务端就知道你在撒谎。再比如,Chrome 浏览器的 Accept-Language 头有一定的格式规律,如果你设置了乱七八糟的值,也会被识别出来。

更进一步,有些反爬系统会检查请求头字段之间的逻辑一致性。举个例子,如果你的 sec-ch-ua-platform 声称是 Windows,但 User-Agent 里写的是 Macintosh,这就矛盾了。又或者你的 Accept-Language 设置了 ja(日语),但你的 IP 地址来自中国大陆,这种组合也很可疑。服务端的检测逻辑就是在寻找这些"不合理"的组合。

还有一种高级的请求头检测方式是"指纹库对比"。反爬服务商会维护一个已知爬虫工具的指纹库,包括各种编程语言 HTTP 库的默认请求头特征。当你的请求匹配到指纹库中的某个特征时,就会被标记为爬虫。这就是为什么简单地修改 User-Agent 不够用——因为你的其他请求头字段可能还暴露了你的真实身份。

IP 封禁机制

IP 封禁是最直接有效的反爬手段。当一个 IP 在短时间内发送大量请求时,服务器会将其加入黑名单。IP 封禁的实现方式有多种,从最简单的频率统计到复杂的机器学习模型都有。

python
# IP封禁的几种形式
ip_ban_types = {
    "频率限制": "单IP每分钟请求次数超过阈值",
    "累计封禁": "单IP累计触发异常达到次数上限",
    "地域封禁": "屏蔽特定地区或国家的IP段",
    "代理识别": "识别并封禁VPN/代理服务器IP",
    "云端封禁": "通过云服务商API识别恶意IP"
}

典型 IP 封禁策略配置示例:

python
ip_rate_limit = {
    "normal_page": {
        "max_requests": 60,      # 最大请求数
        "time_window": 60,      # 时间窗口(秒)
        "ban_duration": 300     # 封禁时长(秒)
    },
    "api_endpoint": {
        "max_requests": 30,
        "time_window": 60,
        "ban_duration": 600
    },
    "sensitive_api": {
        "max_requests": 10,
        "time_window": 60,
        "ban_duration": 3600
    }
}

IP 封禁的核心原理可以用下面的流程图理解:

请求到达服务器


┌──────────────────────┐
│ 提取客户端IP地址      │
└──────┬───────────────┘


┌──────────────────────┐     ┌───────────┐
│ 查询IP是否在黑名单中  │──是──→│ 返回403   │
└──────┬───────────────┘     └───────────┘
       │否

┌──────────────────────┐
│ 查询IP的请求计数      │
│ Redis: ip:count:xxx  │
└──────┬───────────────┘


┌──────────────────────┐     ┌───────────┐
│ 计数是否超过阈值?    │──是──→│ 加入黑名单 │
└──────┬───────────────┘     │ 返回429   │
       │否                    └───────────┘

┌──────────────────────┐
│ 正常处理请求          │
│ 计数+1,设置TTL       │
└──────────────────────┘

应对 IP 封禁的核心方案是建立代理池。代理池的原理很简单:用大量不同的 IP 轮换发送请求,让每个 IP 的请求频率都保持在阈值以下。但代理池的维护是一个复杂的工程问题,包括代理来源管理、质量检测、失效剔除、自动补充等。这部分内容会在第四章详细讲解。

除了代理池,还有一些其他应对 IP 封禁的策略。比如调整请求频率,让请求间隔更加随机化,避免出现规律的请求模式。又比如分散请求时间,把大量请求分摊到较长的时间周期内。再比如使用住宅代理,住宅代理使用的是真实家庭宽带的 IP,比数据中心 IP 更难被识别为爬虫。

在选择代理类型时,需要根据目标网站的反爬强度来决定。对于一般的网站,普通的数据中心代理就够用了。对于反爬严格的网站,可能需要使用住宅代理甚至移动代理。代理的质量直接决定了爬虫的稳定性,便宜的代理往往意味着高失效率和低速度,在代理上省钱通常是得不偿失的。

IP 封禁看似简单,但它背后的对抗逻辑是整个反爬领域最核心的博弈之一。你的代理池质量直接决定了你的爬虫能不能跑下去。

验证码识别体系

验证码是阻挡自动化访问的"门神"。不同类型的验证码难度差异极大,对应的识别方案也完全不同。

验证码类型及难度等级
┌──────────────────────────────────────────┐
│ Level 1: 简单图形验证码                   │
│ ├── 固定位置数字字母                      │
│ ├── 干扰线较少                            │
│ └── OCR可直接识别                         │
├──────────────────────────────────────────┤
│ Level 2: 中等复杂验证码                   │
│ ├── 扭曲变形字符                          │
│ ├── 多干扰线干扰点                        │
│ └── 需要训练模型识别                      │
├──────────────────────────────────────────┤
│ Level 3: 行为验证码                       │
│ ├── 滑动拼图验证                          │
│ ├── 点击特定位置                          │
│ └── 需要模拟鼠标轨迹                      │
├──────────────────────────────────────────┤
│ Level 4: 智能验证码                       │
│ ├── 空间推理题                            │
│ ├── 图形组合逻辑                          │
│ └── 难以自动化,需人工或AI                │
└──────────────────────────────────────────┘

简单图形验证码的 OCR 识别方法:

python
import pytesseract
from PIL import Image
from io import BytesIO
import requests

def recognize_simple_captcha(image_url):
    """简单验证码OCR识别"""
    response = requests.get(image_url)
    image = Image.open(BytesIO(response.content))
    
    # 灰度化处理
    image = image.convert('L')
    
    # 二值化处理
    threshold = 127
    image = image.point(lambda x: 255 if x > threshold else 0)
    
    # OCR识别
    code = pytesseract.image_to_string(image, config='--psm 7')
    return code.strip()

滑动验证码的识别思路则完全不同,需要模拟人类的鼠标拖拽轨迹。人类拖拽滑块时的特征是:先加速后减速,到达目标后会有微小调整。这种轨迹特征本身就是验证码检测的一部分。如果轨迹过于匀速或者过于精准,反而会被判定为机器行为。

除了滑动验证码,现在越来越多的网站开始使用点选验证码。这种验证码要求用户按照特定顺序点击图片中的文字或物体,比如"依次点击所有的红绿灯"。这类验证码的识别需要结合图像识别和自然语言处理技术,难度比滑动验证码高得多。目前主流的解决方案是接入第三方打码平台或者使用深度学习模型。

对于行为验证码,核心思路不是"破解验证码本身",而是"让自动化行为看起来像人类行为"。这包括模拟真实的鼠标移动轨迹、随机的页面停留时间、合理的页面滚动行为等。有些高级的反爬系统甚至会分析你的交互模式,如果你的每次操作都完全一样,就会被判定为机器人。

python
def generate_track(distance):
    """生成模拟人类的滑动轨迹"""
    track = []
    current = 0
    velocity = 0
    # 加速阶段
    while current < distance * 0.7:
        velocity += 2
        current += velocity
        track.append(round(current))
    
    # 减速阶段
    while current < distance:
        velocity = max(velocity - 1, 1)
        current += velocity
        track.append(round(current))
    
    # 微调阶段
    for _ in range(3):
        track.append(distance)
    
    return track

验证码识别的核心不是"破解",而是"模拟"。越是高级的验证码,越注重行为分析而非图形本身。

登录态验证

很多网站的数据需要登录后才能访问,这就要求爬虫能够管理登录态。核心是 Cookie 和 Session 的维护。登录态管理的挑战包括 Cookie 过期处理、多账号轮换、分布式环境下的 Session 共享等。Cookie 过期是最常见的问题,不同的 Cookie 有不同的过期时间,有些是会话级别的(浏览器关闭就失效),有些可以持续几天甚至几个月。你的爬虫需要能够检测 Cookie 是否过期,并在过期时自动重新登录。

多账号轮换是应对频率限制的常用策略。通过多个账号交替使用,可以分散每个账号的请求频率。但多账号管理也带来了新的复杂度:需要维护每个账号的 Cookie、监控账号状态、处理账号被封的情况。

在分布式环境下,Session 共享更是一个挑战。多个爬虫节点需要共享登录态,这通常通过 Redis 等中央存储来实现。每个节点从 Redis 读取 Cookie,使用后更新状态。这种架构需要处理并发冲突、原子性操作等问题。

python
class SessionManager:
    def __init__(self):
        self.session = requests.Session()
        self.cookie_jar = {}
    
    def login(self, username, password):
        """模拟登录获取Cookie"""
        login_url = "https://example.com/login"
        
        # 获取登录页面,提取CSRF Token
        resp = self.session.get(login_url)
        csrf_token = self._extract_csrf(resp.text)
        
        # 提交登录表单
        login_data = {
            "username": username,
            "password": password,
            "csrf_token": csrf_token
        }
        
        self.session.post(login_url, data=login_data)
        self.cookie_jar = self.session.cookies.get_dict()
    
    def _extract_csrf(self, html):
        """提取CSRF Token"""
        import re
        match = re.search(r'name="csrf_token" value="(\w+)"', html)
        return match.group(1) if match else ""

浏览器指纹检测

这是最高级的反爬技术,通过收集浏览器的各种特征生成唯一标识。即使你换了 IP、换了 UA,浏览器指纹依然能识别出你。

浏览器指纹采集项
├── Canvas 指纹      → 绘图引擎差异
├── WebGL 指纹       → 显卡渲染器信息
├── AudioContext     → 音频处理特征
├── 字体指纹         → 系统安装的字体列表
├── 屏幕特征         → 分辨率、色深、像素比
├── 时区信息         → 时区偏移量
├── 语言设置         → 浏览器语言列表
├── 插件列表         → 已安装插件信息
├── 硬件信息         → CPU核心数、设备内存
└── WebRTC 泄露检测   → 真实IP泄漏检测

WebRTC 泄露检测也是指纹采集的重要一环。WebRTC 是浏览器内置的实时通信协议,它可能会泄露用户的真实 IP 地址,即使用户使用了代理。反爬系统可以通过 WebRTC 检测你是否使用了代理,以及你的真实 IP 是什么。这也是为什么在使用代理时,需要确保 WebRTC 也被正确配置或禁用。

浏览器指纹检测原理:

服务器检测流程
┌───────────────┐
│ 加载页面      │
└───────┬───────┘


┌───────────────────────────────┐
│ 注入指纹采集脚本              │
│ 执行Canvas/WebGL等采集操作    │
│ 收集各项浏览器特征数据         │
└───────┬───────────────────────┘


┌───────────────────────────────┐
│ 生成指纹哈希值                │
│ 将特征数据拼接后做哈希        │
│ 发送至服务器进行验证          │
└───────┬───────────────────────┘


┌───────────────────────────────┐
│ 对比指纹数据库                │
│ ┌─────────────────────────┐   │
│ │新指纹 → 正常访问         │   │
│ │已知爬虫指纹 → 拦截       │   │
│ │高频访问指纹 → 限流       │   │
│ │指纹不匹配UA → 可疑       │   │
│ └─────────────────────────┘   │
└───────────────────────────────┘

一个简单的 Canvas 指纹采集示例:

javascript
// 网站端采集Canvas指纹的核心逻辑
function getCanvasFingerprint() {
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    
    ctx.textBaseline = "top";
    ctx.font = "14px 'Arial'";
    ctx.fillStyle = "#f60";
    ctx.fillRect(0, 0, 100, 20);
    ctx.fillStyle = "#069";
    ctx.fillText("fingerprint", 2, 2);
    
    var dataURL = canvas.toDataURL();
    return hash(dataURL);
}

浏览器指纹之所以可怕,是因为它不依赖 Cookie 和 IP,即使你清除了所有缓存、换了网络,指纹依然能追踪到你。

对抗浏览器指纹检测的核心思路是"指纹伪装"。通过修改浏览器环境,让每次访问的指纹都不同,或者让指纹看起来像一个正常的浏览器。Playwright 和 Puppeteer 都提供了修改浏览器指纹的能力,但这项技术在不断演进,反爬系统也在不断升级检测手段。这是一场真正的军备竞赛。

目前主流的指纹对抗方案有三种:第一种是使用指纹浏览器,比如 Multilogin、AdsPower 等专业工具,它们可以生成和管理大量不同的浏览器环境。第二种是使用 Playwright 加上指纹修改插件,通过注入脚本修改 Canvas、WebGL 等特征。第三种是直接分析目标网站的指纹采集逻辑,针对性地修改返回值。每种方案都有优缺点,需要根据实际情况选择。这部分内容会在第八章深入讲解。

1.3 开发环境搭建

Python 环境、IDE 配置、抓包工具安装

工欲善其事,必先利其器。一个良好的开发环境能让你事半功倍。这一节我们来搭建完整的爬虫开发环境。

Python 环境配置

推荐使用 pyenv 管理 Python 版本,避免系统 Python 环境污染。pyenv 的好处是可以在不同项目之间切换 Python 版本,互不影响。

bash
# 安装 pyenv(macOS)
brew install pyenv

# 安装 Python 3.11
pyenv install 3.11.5

# 设置全局版本
pyenv global 3.11.5

# 验证安装
python --version
# Python 3.11.5

创建独立虚拟环境:

bash
# 创建项目目录
mkdir crawler-project && cd crawler-project

# 创建虚拟环境
python -m venv venv

# 激活虚拟环境
source venv/bin/activate  # macOS/Linux
# venv\Scripts\activate   # Windows

# 安装核心依赖
pip install requests lxml beautifulsoup4 parsel
pip install aiohttp httpx
pip install playwright
pip install mitmproxy pyexecjs

推荐的项目依赖配置文件:

txt
# requirements.txt
requests==2.31.0
aiohttp==3.9.1
httpx==0.25.2
lxml==4.9.3
beautifulsoup4==4.12.2
parsel==1.8.1
playwright==1.40.0
pyexecjs==1.5.1
pytesseract==0.3.10
Pillow==10.1.0
redis==5.0.1
pymongo==4.6.0
mysql-connector-python==8.2.0

环境管理是工程化的第一步。很多新手在一台机器上装了十几个项目的依赖,互相冲突,排查问题的时候头都大了。

课程开发环境搭建文档

IDE 配置推荐

VSCode 和 PyCharm 都是不错的选择。VSCode 轻量灵活,适合快速开发和多语言项目;PyCharm 功能强大,适合大型 Python 项目的深度开发。选择哪个主要看个人习惯。

我个人在小型项目中偏好 VSCode,启动快、占用资源少,配合丰富的插件生态足以应对大部分场景。而在处理复杂的大型爬虫项目时,PyCharm 的代码导航、重构工具和调试器会更胜一筹。特别是当你需要调试异步代码或者跟踪复杂的调用链时,PyCharm 的调试器能帮你省去大量排查时间。

不管你选择哪个集成开发环境,有几条配置建议是通用的:第一,启用代码格式化工具,比如 Black 或者 autopep8,保持代码风格统一。第二,配置代码检查工具,比如 pylint 或者 flake8,在编写阶段就发现问题。第三,设置 Python 解释器为虚拟环境,避免依赖冲突。第四,熟悉调试快捷键,断点调试是排查问题的利器。

VSCode 推荐扩展列表:

Python 扩展包
├── Python (ms-python.python)
├── Pylance (ms-python.vscode-pylance)
├── Python Debugger (ms-python.debugpy)
├── autoDocstring (njqdev.python)
└── Python Indent (kevinrose.py)

爬虫开发辅助
├── REST Client (humao.rest-client)      # API测试
├── Thunder Client (ranga.vaghela)        # API测试
├── JSON Viewer (ccimage)                 # JSON格式化
├── XPath Helper (niutech)                # XPath测试
└── Lite XL (yorkxin)                     # JSON高亮

VSCode settings.json 推荐配置:

json
{
    "python.linting.enabled": true,
    "python.linting.pylintEnabled": true,
    "python.formatting.provider": "black",
    "python.analysis.typeCheckingMode": "basic",
    "editor.formatOnSave": true,
    "files.exclude": {
        "**/__pycache__": true,
        "**/*.pyc": true
    }
}

PyCharm 的优势是开箱即用,重点配置三处:Python 解释器设置为虚拟环境;代码风格设置缩进为四个空格;配置 Debug 方便断点调试。PyCharm 的调试功能比 VSCode 强大很多,特别是在处理复杂的异步代码时。

必备工具清单:Python 3.x、PyCharm/VSCode、Chrome DevTools、Fiddler/Charles、mitmproxy

Chrome DevTools 详解

Chrome 开发者工具是最基础也最常用的抓包工具,每个爬虫工程师都必须熟练使用。它不需要安装,打开 Chrome 浏览器按 F12 就能用。

打开方式
├── F12 快捷键
├── 右键 → 检查
└── Ctrl/Cmd + Shift + I

核心面板
├── Network    → 查看所有网络请求
├── Sources    → 查看/调试JS源码
├── Console    → 执行JS代码片段
├── Application → 查看Cookie/Storage
└── Security   → 查看证书信息

Network 面板是爬虫工程师用得最多的面板。几个关键技巧需要掌握:

第一,善用过滤器。Network 面板支持多种过滤语法,可以快速定位目标请求。比如 method:POST 只看 POST 请求,status:403 只看被拒绝的请求,domain:api.example.com 只看特定域名的请求。熟练使用过滤器能大幅提升分析效率。

第二,右键请求可以选择 Copy as cURL,直接获取完整的请求信息,方便在代码中复现。这个功能在调试反爬问题时特别有用,你可以先在浏览器里确认请求能成功,再把完整的请求头搬到代码里。

第三,Preserve Log 选项可以在页面跳转时保留请求记录,这在分析多步骤流程时非常有用。比如登录流程通常涉及多次跳转,如果不勾选这个选项,跳转后的请求会覆盖之前的记录。

mitmproxy 安装与使用

mitmproxy 是一个强大的命令行抓包工具,支持 Python 脚本扩展,可以自动化处理请求和响应。

bash
# 安装
pip install mitmproxy

# 启动代理
mitmproxy -p 8080

# 或使用Web界面
mitmweb -p 8080

编写拦截脚本,可以实时查看和修改请求:

python
# addon.py - mitmproxy脚本示例
from mitmproxy import http

class AntiCrawlerDetector:
    def request(self, flow: http.HTTPFlow):
        """请求拦截"""
        print(f"URL: {flow.request.url}")
        print(f"UA: {flow.request.headers.get('User-Agent', 'N/A')}")
        
    def response(self, flow: http.HTTPFlow):
        """响应拦截"""
        print(f"Status: {flow.response.status_code}")

addons = [AntiCrawlerDetector()]

运行脚本:

bash
mitmdump -s addon.py -p 8080

mitmproxy 相比 Fiddler 和 Charles 的最大优势是可编程性。你可以写脚本自动分析请求模式、修改请求参数、甚至自动解密响应数据。在处理复杂的加密接口时,mitmproxy 的脚本能力能帮你省去大量手动操作。

Fiddler/Charles 配置

Windows 用户推荐 Fiddler,macOS 用户推荐 Charles。两者的核心配置要点如下:

Fiddler 配置:打开 Tools 菜单中的 Options,进入 HTTPS 标签页,勾选 Decrypt HTTPS traffic 来解密 HTTPS 流量。然后配置证书信任,设置过滤规则只显示目标域名的请求。Fiddler 还支持导出 HAR 格式数据,方便与团队共享抓包结果。

Charles 配置:打开 Proxy 菜单中的 SSL Proxying Settings,添加要抓取的域名(支持通配符)。安装 Charles 根证书并设为信任。Charles 的 Rewrite 功能可以修改请求和响应,在调试时非常有用。另外 Charles 的 Map Local 功能可以将线上请求映射到本地文件,方便调试。

Playwright 安装

Playwright 是新一代浏览器自动化工具,支持 Chromium、Firefox 和 WebKit 三大浏览器引擎。相比 Selenium,它更快、更稳定,API 也更现代。

bash
# 安装
pip install playwright

# 安装浏览器驱动
playwright install

# 安装特定浏览器
playwright install chromium

Playwright 基础用法示例:

python
from playwright.sync_api import sync_playwright

def crawl_with_playwright():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        context = browser.new_context(
            user_agent="Mozilla/5.0 ...",
            viewport={"width": 1920, "height": 1080}
        )
        page = context.new_page()
        page.goto("https://example.com")
        page.wait_for_selector(".content")
        title = page.locator("h1").text_content()
        page.screenshot(path="screenshot.png")
        browser.close()

Playwright 的核心优势在于它运行真实的浏览器环境,包括 JavaScript 执行、Canvas 渲染、WebGL 等,因此可以有效对抗很多反爬手段。当然,代价是资源消耗更大、速度更慢。在后面的章节中,我们会详细讲解如何用 Playwright 对抗浏览器指纹检测。

环境验证脚本

运行以下脚本验证环境配置是否完整:

python
# check_env.py
import sys

def check_environment():
    """环境检查脚本"""
    checks = []
    
    version = sys.version_info
    if version.major >= 3 and version.minor >= 10:
        checks.append("Python版本正常: " + sys.version.split()[0])
    else:
        checks.append("Python版本过低,需要3.10+")
    
    libs = ['requests', 'lxml', 'bs4', 'aiohttp', 'playwright']
    for lib in libs:
        try:
            __import__(lib)
            checks.append(f"{lib} 已安装")
        except ImportError:
            checks.append(f"{lib} 未安装,请运行 pip install {lib}")
    
    print("\n".join(checks))

if __name__ == "__main__":
    check_environment()

预期输出:

Python版本正常: 3.11.5
requests 已安装
lxml 已安装
bs4 已安装
aiohttp 已安装
playwright 已安装

必备工具清单汇总

最后给你一个完整的工具清单,照着准备就行:

开发工具
├── Python 3.10+        # 核心运行环境
├── pip/poetry           # 包管理工具
├── VSCode/PyCharm       # IDE
└── Git                  # 版本控制

抓包分析
├── Chrome DevTools      # 浏览器内置,必会
├── mitmproxy            # Python抓包库,可编程
├── Fiddler (Windows)    # GUI抓包工具
└── Charles (macOS)      # GUI抓包工具

浏览器自动化
├── Playwright           # 新一代自动化工具,推荐
├── Selenium             # 传统自动化工具,兼容性好
└── Chrome/Edge          # 浏览器本体

辅助工具
├── Postman/Insomnia     # API测试工具
├── JSON Editor Online   # JSON处理
├── XPath Helper         # XPath测试
└── Regex101             # 正则表达式在线测试

磨刀不误砍柴工。花一天时间把环境搭好,比之后每天跟环境问题作斗争要划算得多。

新手 vs 老手的区别

最后,用一个对比来结束本章。爬虫新手和老手的区别不在于会写多少代码,而在于思维方式:

新手思维                          老手思维
├── 拿到需求直接写代码            ├── 先分析目标网站架构和反爬策略
├── 被封了就换UA                  ├── 被封了先分析封禁原因
├── 遇到验证码就手动输入          ├── 遇到验证码先评估识别成本
├── 单线程跑,慢就加并发          ├── 先评估目标承受能力再定并发
├── 出错就重试,无限重试          ├── 设计有限重试加指数退避
├── 数据直接存文件                ├── 数据去重加质量校验加结构化存储
├── 跑完就完事                    ├── 持续监控加告警加日志
└── 复制别人的代码                ├── 理解原理后写自己的框架

新手拿到需求的第一反应是"怎么写代码把数据抓下来",老手的第一反应是"这个网站的架构是什么样的,用了哪些反爬手段,数据量有多大,更新频率是多少,采集策略应该怎么定"。思维方式的差异决定了最终方案的质量。

举个具体的例子。新手遇到一个需要登录的网站,通常会直接在代码里硬编码用户名密码,然后每次都走一遍登录流程。老手会先分析登录接口的参数结构,搞清楚 Token 的有效期和刷新机制,设计一个 Session 管理器来复用登录态,还会加上异常处理和自动重连逻辑。同样是"登录后抓数据"这件事,新手的代码可能跑两次就被封了,老手的代码能稳定跑几个月。

再比如数据存储。新手通常把数据直接写入 CSV 文件或者 JSON 文件,数据量一大就会出现各种问题:文件太大打不开、数据格式不一致、重复数据无法去重。老手会从一开始就设计好数据模型,选择合适的存储方案(MySQL、MongoDB 还是 Redis),建立索引和去重机制,确保数据的完整性和可查询性。

新手关注"能不能跑起来",老手关注"能不能稳定跑下去"。

课程导学总结

这门课程的设计理念是"实战驱动,原理先行"。每一章都会从实际问题出发,讲清楚原理,再给出可复用的代码模板。

你将获得:完整的反爬技术知识体系、经过验证的代码实战案例、可直接复用的工具模板、以及持续更新的技术方案。

学习建议:跟着章节顺序循序渐进,每章的代码都动手敲一遍。遇到问题先独立思考,再查阅文档和资料。把踩过的坑记录下来,这些就是你最宝贵的经验。爬虫技术的学习是一个螺旋上升的过程,你会发现自己反复遇到同样的问题,但每次的理解深度都在增加。

另外,建议在学习过程中建立自己的工具库和代码片段库。每次解决一个新问题,就把相关的代码封装成可复用的函数或类。随着时间推移,你会积累出一套属于自己的爬虫框架,这比使用别人的框架更顺手,也更能应对各种定制化需求。

最后,要养成阅读源码的习惯。requests、aiohttp、playwright 这些库的源码里藏着大量实战经验,阅读源码能帮你深入理解 HTTP 协议和浏览器自动化的底层原理。不要只停留在"会调用接口"的层面,要深入到"理解原理"的层次。当你理解了底层原理,遇到任何反爬问题都能从根本出发去思考和解决,而不是在网上找现成的答案。

爬虫工程师的成长没有捷径,但有正确的方向。这个系列教程就是怕浪猫为你规划的路线图,接下来就看你自己的执行力了。每一章都认真学、认真练,十一章学完,你会发现自己对爬虫的理解已经上了一个大台阶。

真正的高手不是学会所有反爬技巧,而是理解本质后能快速找到最优解。

觉得有用?收藏起来,下次直接照抄。

你在爬虫中遇到过最棘手的反爬是什么?评论区说说,怕浪猫专门写一期详解。

关注怕浪猫,下期我们讲 HTTP 网络基础——从 HTTPS 加密原理到请求头反爬识别,打好网络基础才能做好爬虫。

系列进度 1/11

下章预告: 第 2 章将深入 HTTP 网络基础知识,从 HTTPS 加密原理到请求头反爬识别,打好网络基础才能做好爬虫。我们将用图解的方式拆解 TLS 握手过程,详解每个请求头字段在反爬中的应用场景,让你从根本上理解为什么爬虫会被识别。

怕浪猫说: 学习爬虫就像武功修炼,招式可以速成,但内功需要时间沉淀。HTTP 协议就是内功基础,地基打好了,后面的反爬对抗才能游刃有余。下章见。

热爱生活,喜好美食,追求未来!