Python爬取笔趣阁小说:从零构建可搜索的批量下载器(附源码)

1. 为什么选择Python爬取笔趣阁小说?

作为一个经常追更网络小说的老书虫,我深知手动复制粘贴章节的痛苦。去年我用Python写了个笔趣阁小说下载器之后,每周能省下至少3小时追更时间。这个项目特别适合Python初学者练手——既能学到requests网络请求XPath解析这些核心技能,又能做出实用的工具。

相比其他爬虫项目,笔趣阁有三大优势:一是网页结构简单,没有复杂反爬;二是内容纯文本,不需要处理图片验证码;三是数据量大,单本小说就有几百个章节页面,能充分练习循环和异常处理。我带的编程新手学员第一个实战项目基本都是这个,成功率高达90%。

2. 环境准备与依赖安装

2.1 Python版本选择

推荐使用Python 3.8+版本,我在Windows 10和MacOS Monterey上都测试通过。用以下命令检查版本:

python --version # 或 python3 --version

如果版本低于3.8,建议通过 Python官网 升级。安装时务必勾选"Add Python to PATH"选项。

2.2 必备库安装

打开终端运行这些命令:

pip install requests lxml tqdm
  • requests:比urllib更人性化的HTTP库
  • lxml:解析HTML的神器,比BeautifulSoup快3倍
  • tqdm:给循环加进度条,避免程序假死焦虑

遇到过安装报错的同学可以试试清华源:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests lxml tqdm

3. 网页结构分析与爬取策略

3.1 笔趣阁的页面特点

以《圣墟》为例,它的目录页URL是http://www.biquzw.com/13/13959/。打开开发者工具(F12)能看到:

  1. 所有章节链接都在<dd>标签下的<a>标签里
  2. 章节URL是相对路径,需要拼接域名
  3. 正文内容在<div id="content">中,段落用<br>分隔

3.2 反爬机制应对

笔趣阁的反爬比较温和,但建议:

  1. 添加User-Agent头模拟浏览器
  2. 每请求一个页面sleep 1秒
  3. 遇到503错误时自动重试

这是我常用的请求头:

headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" }

4. 核心代码实现

4.1 目录爬取与解析

def get_chapter_list(url): import requests from lxml import etree from tqdm import tqdm res = requests.get(url).content html = etree.HTML(res) chapters = [] base_url = "http://www.biquzw.com" for link in tqdm(html.xpath("//dd/a/@href"), desc="解析目录"): full_url = base_url + link chapters.append(full_url) return chapters

这段代码的关键点:

  • etree.HTML将HTML转为可查询对象
  • //dd/a/@href这个XPath获取所有章节链接
  • tqdm包装迭代对象显示进度条

4.2 正文内容提取

def get_chapter_content(url): res = requests.get(url).content html = etree.HTML(res) content = html.xpath("//div[@id='content']/text()") cleaned = [text.strip() for text in content if text.strip()] return "\n".join(cleaned)

处理正文时的常见问题:

  • strip()去除首尾空白
  • 过滤空字符串if text.strip()
  • 用换行符连接段落

5. 批量下载与本地存储

5.1 文件存储优化

不建议一次性写入所有内容,改用追加模式:

with open("novel.txt", "a", encoding="utf-8") as f: for i, url in enumerate(chapters): content = get_chapter_content(url) f.write(f"第{i+1}章\n{content}\n\n") time.sleep(1) # 礼貌爬取

5.2 断点续爬实现

突然中断后重新爬取很麻烦,可以记录已下载章节:

if os.path.exists("progress.log"): with open("progress.log", "r") as f: downloaded = set(f.read().splitlines()) else: downloaded = set() for url in chapters: if url in downloaded: continue # 下载代码... with open("progress.log", "a") as f: f.write(url + "\n")

6. 功能扩展:小说搜索

6.1 搜索接口分析

通过抓包发现笔趣阁搜索是POST请求:

search_url = "http://www.biquzw.com/modules/article/search.php" params = { "searchkey": "圣墟", "submit": "" } response = requests.post(search_url, data=params)

6.2 搜索结果解析

用XPath提取书名和URL:

html = etree.HTML(response.text) books = html.xpath("//tr[@id='nr']/td[1]/a") for book in books: title = book.xpath("./text()")[0] link = book.xpath("./@href")[0]

7. 完整源码与使用教程

项目已上传GitHub,包含:

  • 基础爬取版basic_crawler.py
  • 带搜索功能版search_crawler.py
  • 图形界面版(用PySimpleGUI实现)

使用方法:

git clone https://github.com/example/novel-crawler cd novel-crawler python search_crawler.py

输入书名后会自动:

  1. 搜索并显示结果列表
  2. 选择要下载的书籍
  3. 显示实时下载进度
  4. 生成格式化的TXT文件

8. 常见问题解决方案

Q1 中文乱码怎么办?

  • 确保文件用utf-8编码打开
  • 请求后设置response.encoding = 'utf-8'

Q2 被封IP了怎么处理?

  • 使用代理IP池(需自行搭建)
  • 降低请求频率到2秒/页
  • 修改User-Agent模拟不同设备

Q3 章节顺序错乱?

  • 检查目录页的排序是否正常
  • 在文件名前补零:f"{i:04d}.txt"

最后提醒:爬取公开数据请遵守robots.txt协议,不要给服务器造成过大压力。这个项目仅用于学习交流,建议下载后24小时内删除。