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 tqdm3. 网页结构分析与爬取策略
3.1 笔趣阁的页面特点
以《圣墟》为例,它的目录页URL是http://www.biquzw.com/13/13959/。打开开发者工具(F12)能看到:
- 所有章节链接都在
<dd>标签下的<a>标签里 - 章节URL是相对路径,需要拼接域名
- 正文内容在
<div id="content">中,段落用<br>分隔
3.2 反爬机制应对
笔趣阁的反爬比较温和,但建议:
- 添加User-Agent头模拟浏览器
- 每请求一个页面sleep 1秒
- 遇到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输入书名后会自动:
- 搜索并显示结果列表
- 选择要下载的书籍
- 显示实时下载进度
- 生成格式化的TXT文件
8. 常见问题解决方案
Q1 中文乱码怎么办?
- 确保文件用
utf-8编码打开 - 请求后设置
response.encoding = 'utf-8'
Q2 被封IP了怎么处理?
- 使用代理IP池(需自行搭建)
- 降低请求频率到2秒/页
- 修改User-Agent模拟不同设备
Q3 章节顺序错乱?
- 检查目录页的排序是否正常
- 在文件名前补零:
f"{i:04d}.txt"
最后提醒:爬取公开数据请遵守robots.txt协议,不要给服务器造成过大压力。这个项目仅用于学习交流,建议下载后24小时内删除。