小说爬虫

该专题还在整理中。

小说爬虫这件事,技术门槛比大多数人想象的低,但踩坑的概率比大多数人想象的高——真正难的从来不是”把字抓下来”,而是”抓得干净、存得规整、还不把自己送进去”。

我自己断断续续写过七八个小说爬虫,从最早的某点、某横,到后来的各类免费站、镜像站,踩过的坑包括但不限于:编码乱码、反爬封 IP、章节顺序错乱、正文里混广告、抓了一半网站跑路。下面把整套东西拆开讲一遍,尽量讲人话,也尽量讲全。

一、先想清楚:你要爬的是什么类型的小说站

不同站点的技术形态,直接决定你用什么方案。大致可以分四类:

站点类型 典型特征 难度 推荐方案
静态 HTML 站 章节列表和正文都在源码里,无 JS 渲染 requests + BeautifulSoup / lxml
JS 渲染站 正文靠 Ajax 或前端框架加载 抓接口 / Playwright
强反爬站 Cloudflare、验证码、字体加密 Playwright + 代理池 + 字体解密
App / 小程序 无网页版,只能抓包 mitmproxy 抓包 + 接口复现

我的建议是:优先选静态站,其次选有公开接口的站,实在不行再上浏览器自动化。用 Playwright 抓一万章,慢到你会怀疑人生。

二、核心流程:一个小说爬虫的六个环节

1. 找目录页,拿到章节 URL 列表

大多数小说站的目录页结构是固定的,比如 /book/12345/ 下面挂着所有章节链接。用 CSS 选择器或 XPath 一次性抽出来即可。

坑点在于:

  • 有些站目录分页,只显示前 100 章,剩下的要翻页;
  • 有些站目录是 JS 动态加载的,源码里根本没有;
  • 有些站章节顺序是倒序的,别抓完才发现要 reverse。

2. 逐章请求正文页

这一步是最容易被封的地方。几个基本纪律:

  • 加延时:每请求之间 sleep 0.5~2 秒,随机化,别固定值;
  • 带 UA 和 Referer:裸 requests 的默认 UA 一眼假;
  • 控制并发:单站并发别超过 3~5,用 asyncio + Semaphore 或线程池都行;
  • 失败重试:用 tenacity 或自己写指数退避,别一失败就丢章节。

3. 解析正文

正文一般在某个 <div id="content"><div class="read-content"> 里。但真正的脏活是清洗:

  • 去掉 <script><style>、广告 div;
  • <br> 转成换行,把 &nbsp; 转成空格;
  • 去掉”请记住本站域名””手机阅读请访问 xxx”这类插入语;
  • 统一全角/半角标点,处理乱码(尤其是 GBK 站)。

我一般会写一个 clean_text() 函数,用正则批量清,比 BeautifulSoup 的 get_text() 干净得多。

4. 编码处理

老站点大量使用 GBK / GB2312,直接 response.text 会乱码。正确做法:

  1. 先看 response.encoding,如果是 ISO-8859-1,多半是网站没声明;
  2. chardetcharset-normalizer 探测;
  3. 或者直接 response.content.decode('gbk', errors='ignore')

5. 存储

常见三种格式,各有适用场景:

格式 优点 缺点
TXT 简单、通用、随便什么阅读器都能开 没有章节结构,元数据难存
EPUB 有目录、有封面、阅读体验好 生成麻烦,需要 ebooklib 之类库
数据库(SQLite) 便于增量更新、断点续传 最终还要导出

我自己的习惯是:SQLite 存原始数据 + TXT 导出成品。断点续爬时查一下哪章没抓,直接跳过,非常省事。

6. 增量与断点续传

长篇小说动辄几千章,中途断网、被封、关机是常态。设计时就要考虑:

  • 每章抓完立刻落库,别攒在内存里;
  • (book_id, chapter_index) 做唯一键,重复抓自动覆盖;
  • 启动时先查已完成的最大章节号,从下一章继续。

三、反爬对抗:哪些手段值得花时间,哪些不值得

先给个态度:大部分小说站的反爬都很弱,真正需要重武器的是少数。按投入产出比排序:

  1. UA + Referer + Cookie:成本最低,收益最高,先做这个;
  2. 请求间隔随机化:几乎零成本,能躲掉大部分基于频率的封禁;
  3. 代理 IP 池:免费代理基本不能用,付费代理按量计费,成本不低,除非目标站封得狠,否则不必;
  4. Playwright / Selenium:能过 JS 渲染和部分反爬,但速度慢 10 倍以上,只在必要时用;
  5. 字体加密破解:某些站把数字或部分汉字用自定义字体映射,需要下载 woff 文件、解析字形坐标反推,属于进阶玩法;
  6. 打码平台:遇到验证码再考虑,一般小说站不至于。

如果目标站用了 Cloudflare 的 5 秒盾,可以试试 cloudscraper,或者直接用 Playwright 走真实浏览器指纹。

四、法律与道德:这块必须说清楚

技术归技术,但小说爬虫这件事,法律风险是真实存在的,不是吓唬人。

  • 著作权:小说正文受版权保护,抓取后自用一般问题不大,但公开传播、二次分发、商业使用是明确侵权的;
  • robots.txt:不是法律,但是网站明确表达意愿的方式,无视它会在道德和某些司法实践里处于不利地位;
  • 反不正当竞争:如果抓取行为对网站服务器造成实质负担,或获取的是对方核心数据资产,可能触及这条;
  • 个人信息:如果站内有用户评论、ID 等信息,别碰。

我的个人原则:只抓公开可访问的正文、控制频率、不传播、不商用。如果你打算做产品或者公开分享,请先去谈授权。

五、工具与库推荐

用途 推荐 说明
HTTP 请求 httpx / requests httpx 支持 async,写并发更舒服
HTML 解析 lxml / BeautifulSoup / parsel lxml 最快,parsel 支持 XPath + CSS
浏览器自动化 Playwright 比 Selenium 快、API 友好
编码探测 charset-normalizer chardet 的现代替代
重试 tenacity 装饰器式,写起来干净
EPUB 生成 ebooklib 能生成带目录的 epub
抓包 mitmproxy 对付 App 端必备

六、一个最小可用骨架(伪代码思路)

不贴完整代码,讲思路,你按自己目标站改:

  1. 用 httpx 建一个带 headers 的 Client;
  2. 请求目录页,用 parsel 抽出 (章节名, URL) 列表;
  3. 查 SQLite,过滤掉已抓的章节;
  4. for 循环,每章:请求 → 解析正文 → 清洗 → 入库 → sleep(random);
  5. 全部抓完后,从库里读出来拼成 TXT 或生成 EPUB。

就这么简单。真正花时间的是针对每个站写选择器和清洗规则。

七、几个常见坑,提前避

  • 章节顺序错乱:别信目录页的顺序,用章节号或 URL 里的数字排序;
  • 正文里混广告:写正则匹配”本站””域名””最新章节”等关键词批量删;
  • 网站改版:选择器写死会挂,尽量用结构性 XPath 而不是 class 名;
  • 内存爆掉:几千章全攒内存里会炸,边抓边落盘;
  • 被封 IP:家里宽带被封一般重启光猫能换 IP,云服务器就别指望了。

相关问题

Q1:爬小说用什么语言最好?
Python 生态最全,requests + parsel + SQLite 就能搞定 90% 的站。Node.js 也行,但 HTML 解析库没 Python 顺手。

Q2:遇到 Cloudflare 验证怎么办?
先试 cloudscraper,不行就上 Playwright 走真实浏览器。再不行,这个站可能不值得你花这个时间。

Q3:爬下来的 txt 乱码怎么修?
九成是编码问题,用 charset-normalizer 探测后重新 decode;剩下一成是字体加密,需要解析 woff 文件,属于另一个话题。

Q4:能不能用 AI 帮我自动写爬虫?
可以。把目标页面的 HTML 片段丢给大模型,让它生成选择器和清洗正则,效率很高。但反爬逻辑和断点续传还是得自己设计。

Q5:抓下来的小说能发到网上吗?
不建议。正文有版权,公开传播属于侵权。自己看、做个人书库没问题,分享和商用请先拿授权。

内容由 AI 生成,产品信息请以官网为准。