当前位置: 首页 > news >正文

Python协程实战:异步高效爬取《鬼神传》全本小说

一、项目背景

在网络爬虫开发中,同步爬取大量小说章节时效率低下,等待IO时间过长。本文将使用Python协程和异步IO技术,结合 aiohttp 、 asyncio 、 aiofiles 实现高并发、高效率的小说爬取,大幅提升下载速度。

二、技术选型


异步HTTP请求:aiohttp

异步文件写入:aiofiles

HTML解析:lxml

协程调度:asyncio

网页请求:requests

三、完整代码实现

import requests from lxml import etree import time import asyncio import aiohttp import aiofiles import os BASE_URL = "https://www.zanghaihua.org" # 获取所有章节链接 def get_every_chapter_url(url): headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" } resp = requests.get(url, headers=headers) resp.encoding = "utf-8" tree = etree.HTML(resp.text) a_list = tree.xpath('//dl[@class="gs-booklist-dl"]//dd/a') href_list = [] title_list = [] for a in a_list: href = a.xpath('./@href')[0] title = a.xpath('./text()')[0] full_url = BASE_URL + href href_list.append(full_url) title_list.append(title) print(f"成功获取 {len(href_list)} 章目录") return href_list, title_list # 下载单章 async def download_one(session, url, title): headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept-Encoding": "gzip, deflate" } try: async with session.get(url, headers=headers, timeout=20) as resp: page_text = await resp.text(encoding="utf-8", errors="ignore") tree = etree.HTML(page_text) content_list = tree.xpath('//div[@class="gs-article-text"]//p//text()') content = "\n".join([text.strip() for text in content_list if text.strip()]) if not os.path.exists("./鬼神传"): os.mkdir("./鬼神传") async with aiofiles.open(f"./鬼神传/{title}.txt", "w", encoding="utf-8") as f: await f.write(title + "\n\n" + content) print(f"已保存:{title}") except Exception as e: print(f"下载失败 {title}:{e}") # 批量下载 async def download(href_list, title_list): async with aiohttp.ClientSession() as session: tasks = [] for url, title in zip(href_list, title_list): task = asyncio.create_task(download_one(session, url, title)) tasks.append(task) await asyncio.gather(*tasks) # 主函数 def main(): start = time.time() book_url = "https://www.zanghaihua.org/guwen/guishenchuan/" href_list, title_list = get_every_chapter_url(book_url) asyncio.run(download(href_list, title_list)) end = time.time() print(f"《鬼神传》全部下载完成!总耗时:{end - start:.2f} 秒") if __name__ == "__main__": main()

四、代码详解

1. 目录获取函数(同步)

def get_every_chapter_url(url): # 请求头伪装浏览器 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" } resp = requests.get(url, headers=headers) resp.encoding = "utf-8" tree = etree.HTML(resp.text) # XPath提取所有章节链接与标题 a_list = tree.xpath('//dl[@class="gs-booklist-dl"]//dd/a')

用 requests 同步获取目录页(目录页仅1次请求,同步无性能影响)

XPath 精准定位章节 <a> 标签,提取 href 与 title

2. 单章异步下载

async def download_one(session, url, title): async with session.get(url, headers=headers, timeout=20) as resp: page_text = await resp.text(encoding="utf-8", errors="ignore") tree = etree.HTML(page_text) content_list = tree.xpath('//div[@class="gs-article-text"]//p//text()')

async/await 实现异步非阻塞请求

session.get 复用连接,提升效率

异常捕获保证单个章节失败不影响整体

3. 异步批量下载

async def download(href_list, title_list): async with aiohttp.ClientSession() as session: tasks = [asyncio.create_task(download_one(session, url, title)) for url, title in zip(href_list, title_list)] await asyncio.gather(*tasks)

创建任务列表, gather 并发执行

真正实现多章节同时下载,速度提升10~50倍

4. 主函数调度

def main(): start = time.time() href_list, title_list = get_every_chapter_url(book_url) asyncio.run(download(href_list, title_list)) end = time.time() print(f"《鬼神传》全部下载完成!总耗时:{end - start:.2f} 秒")

计时统计,直观展示异步爬取效率

五、运行效果

几十章内容10秒内完成,同步爬取需30秒以上


六、关键优化点

1. 连接复用: aiohttp.ClientSession 减少TCP握手开销

2. 异步文件: aiofiles 避免磁盘IO阻塞事件循环

3. 异常处理:单章下载失败不中断整体任务

4. 编码兼容: errors="ignore" 避免乱码崩溃

5. 目录自动创建:自动生成 ./鬼神传 文件夹

七、注意事项

1. 遵守网站 robots.txt 协议,请勿用于商业用途

2. 合理设置并发量,避免给服务器造成压力

3. 可添加延时、代理IP进一步降低风险

4. 本代码仅用于学习Python协程与爬虫技术

八、总结

通过 asyncio + aiohttp + aiofiles 实现的异步协程爬虫,完美解决了同步爬虫IO阻塞问题,在小说、图片、网页批量下载场景中效率极高。
掌握这套技术,可轻松应对大批量、高并发的数据采集需求。



本文为原创技术文章,禁止转载

http://www.zskr.cn/news/1436313.html

相关文章:

  • 基于Arduino与433MHz模块的无线距离报警器设计与实现
  • 3步掌握YimMenu:GTA5开源防护工具完全实战指南
  • Jamstack开发:构建高性能静态网站
  • 黄大年茶思屋榜文132期 储能篇 第1题 储能锂离子大电芯析锂无损检测
  • Ubuntu 22.04上vsftpd的550目录切换错误,别急着改权限,先看看这个chroot配置
  • 深度学习生成模型(三)—— 扩散模型:DDPM 与 Stable Diffusion(五十一)
  • 基于Arduino的随机按键门锁:用动态映射提升物理安全
  • Latest Verification Report of Official Rolex After-Sales Service Centers – June 2026 - 资讯纵览
  • 别再被查重费割韭菜了!这个AI平台的免费查重功能,99%的毕业生还不知道
  • 深度学习生成模型(四)—— 自编码器与表征学习(五十二)
  • 基于Arduino的AI猜数游戏:从有限状态机到模块化智能体设计
  • 百度网盘秒传脚本:5分钟快速上手,告别文件分享失效烦恼
  • 手把手教你离线搞定CUDA和cuDNN:从下载到配置,再到打包迁移完整流程(含超算实战)
  • Gemini跨境数据脱敏策略失效真相:动态掩码密钥轮转机制(附AWS KMS+HashiCorp Vault双活配置模板)
  • 基于TCS3200与Arduino的智能画框灯光反馈系统实战
  • Gemini服务条款变更实录:从免费试用到商用收费的3个临界点,及替代方案迁移时间窗(仅剩18天)
  • 构建高可用音乐播放器:洛雪音乐多平台音源集成实战指南
  • 2026年10款论文降AI率网站横评:从90%降至10%的宝藏之选
  • 解锁2026浪琴官方售后新体验:实地鉴证服务全面革新新址及售后热线启用 - 资讯纵览
  • 深度学习生成模型(五)—— 自回归生成与 Normalizing Flow(五十三)
  • 2026年8月四川7天6晚纯玩团推荐|用户评价、费用参考与避坑指南 - 随峰国旅
  • 微信聊天记录永久保存完全指南:告别数据丢失的终极解决方案
  • JDK源码学习从入门到精通!
  • 如何快速配置ok-ww鸣潮自动化工具:面向新手的完整实践指南
  • 告别依赖Vivado!手把手教你用Modelsim独立仿真Vivado IP核(附PLL报错解决方案)
  • ArcGIS Enterprise 10.8 Linux部署后,如何用命令行高效运维?这些脚本和诊断工具你得知道
  • 携程0510笔试真题【删除】
  • Java架构六大核心专题面试宝典公开,程序员突击必备!
  • 影视制片人紧急通告:AI剧本审核新规落地(Gemini辅助写作合规白皮书首发),错过将影响成片备案资质
  • Arduino超声波测距与分级报警系统:从HC-SR04到社交距离提醒器