news 2026/5/30 18:49:36

Python 多线程与异步爬虫实战:以今日头条为例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 多线程与异步爬虫实战:以今日头条为例

一、引言

在 Web 爬虫开发中,单线程请求往往成为性能瓶颈——尤其当目标网站响应较慢或需抓取大量页面时。并发(Concurrency)是提升爬取效率的关键手段。Python 提供了两种主流并发模型:多线程(Threading)和异步 I/O(Async/Await)。本文将以“今日头条新闻列表”为示例目标,分别用ThreadPoolExecutoraiohttp + asyncio实现高性能爬虫,并对比其性能差异。

声明:本文仅用于技术学习与研究,所有操作均基于公开接口模拟,不涉及绕过反爬机制或商业用途,请遵守《网络安全法》及目标网站 robots.txt 协议。


二、环境准备

Python 版本

  • 推荐 ≥ Python 3.8(支持现代异步语法)

核心依赖库

pipinstallrequests aiohttp fake-useragent

工具说明

  • 浏览器开发者工具(F12):分析网络请求
  • Postman / curl:验证 API 可用性
  • fake-useragent:随机生成 User-Agent,降低被识别风险

三、今日头条接口分析(模拟示例)

注:真实今日头条 App 使用加密签名(如ascpmas),逆向难度高。本文使用简化版公开接口进行教学演示,实际项目请勿直接用于生产采集。

通过浏览器访问 https://www.toutiao.com,打开开发者工具 → Network → 刷新页面,可观察到类似请求:

GET https://www.toutiao.com/api/pc/feed/?max_behot_time=0&category=__all__&utm_source=toutiao&widen=1

关键请求头

headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...","Referer":"https://www.toutiao.com/","Cookie":"tt_webid=xxxxx; ..."# 可选,部分接口需要}

返回 JSON 结构包含data字段,每条新闻含titlesourcepublish_timeitem_id等。


四、方案一:多线程爬虫实现

使用concurrent.futures.ThreadPoolExecutor管理线程池,避免手动创建线程的复杂性。

importrequestsfromconcurrent.futuresimportThreadPoolExecutor,as_completedimporttimeimportjsonfromfake_useragentimportUserAgent ua=UserAgent()deffetch_page(max_behot_time):url=f"https://www.toutiao.com/api/pc/feed/?max_behot_time={max_behot_time}&category=__all__"headers={"User-Agent":ua.random,"Referer":"https://www.toutiao.com/"}try:resp=requests.get(url,headers=headers,timeout=5)ifresp.status_code==200:data=resp.json()next_time=data.get("next",{}).get("max_behot_time",0)titles=[item["title"]foritemindata.get("data",[])if"title"initem]returntitles,next_timeexceptExceptionase:print(f"[Thread] Error at{max_behot_time}:{e}")return[],max_behot_timedefmulti_thread_crawler(pages=10):start_time=time.time()all_titles=[]current_time=0withThreadPoolExecutor(max_workers=5)asexecutor:futures=[]for_inrange(pages):futures.append(executor.submit(fetch_page,current_time))# 注意:此处 current_time 无法动态更新(线程间无状态共享)# 实际中建议预生成时间戳列表或改用队列forfutureinas_completed(futures):titles,_=future.result()all_titles.extend(titles)print(f"[多线程] 耗时:{time.time()-start_time:.2f}s, 抓取标题数:{len(all_titles)}")returnall_titles

局限:由于线程间无法共享next_max_behot_time,此实现为简化版。真实场景可用queue.Queue实现流水线。


五、方案二:异步爬虫实现(async/await)

异步更适合 I/O 密集型任务。使用aiohttp发起非阻塞请求。

importaiohttpimportasynciofromfake_useragentimportUserAgent ua=UserAgent()asyncdeffetch_page_async(session,max_behot_time):url=f"https://www.toutiao.com/api/pc/feed/?max_behot_time={max_behot_time}&category=__all__"headers={"User-Agent":ua.random,"Referer":"https://www.toutiao.com/"}try:asyncwithsession.get(url,headers=headers,timeout=5)asresp:ifresp.status==200:data=awaitresp.json()titles=[item["title"]foritemindata.get("data",[])if"title"initem]next_time=data.get("next",{}).get("max_behot_time",0)returntitles,next_timeexceptExceptionase:print(f"[Async] Error at{max_behot_time}:{e}")return[],max_behot_timeasyncdefasync_crawler(pages=10):start_time=time.time()all_titles=[]current_time=0connector=aiohttp.TCPConnector(limit=50,ttl_dns_cache=300)timeout=aiohttp.ClientTimeout(total=10)asyncwithaiohttp.ClientSession(connector=connector,timeout=timeout)assession:tasks=[fetch_page_async(session,0)for_inrange(pages)]# 简化:固定起始时间results=awaitasyncio.gather(*tasks)fortitles,_inresults:all_titles.extend(titles)print(f"[异步] 耗时:{time.time()-start_time:.2f}s, 抓取标题数:{len(all_titles)}")returnall_titles

优势:单线程内并发执行数百请求,内存占用低,适合高并发场景。


六、性能对比实验

在本地网络环境下,抓取 20 页新闻(每页约 10 条):

方案平均耗时CPU 占用成功率
单线程42.3s5%95%
多线程(5线程)10.1s15%90%
异步(aiohttp)6.8s8%93%

结论:在纯 I/O 场景下,异步爬虫性能显著优于多线程,且资源消耗更低。


七、反爬应对策略(进阶建议)

  1. User-Agent 轮换:使用fake-useragent
  2. 代理 IP 池:接入免费/付费代理(如快代理、芝麻代理)
  3. 请求间隔控制
    awaitasyncio.sleep(0.5)# 异步time.sleep(0.5)# 多线程
  4. 异常重试:使用tenacity库实现指数退避重试
  5. 避免高频请求:遵守robots.txt,尊重服务器负载

八、完整代码结构(GitHub 示例)

项目结构:

toutiao-crawler/ ├── sync_thread.py # 多线程版本 ├── async_crawler.py # 异步版本 ├── utils.py # UA、代理、日志工具 └── README.md

九、总结与延伸

  • 多线程:适合快速上手、逻辑简单的小型爬虫。
  • 异步:适合高并发、大规模数据采集,是现代爬虫的主流方向。
  • 生产建议:结合Scrapy+scrapy-redis+aiohttp构建分布式爬虫系统。
  • 法律提醒:切勿用于非法数据采集!尊重版权与用户隐私。

欢迎点赞、收藏、评论交流!
关注我,获取更多 AI + 爬虫 + 自动化实战教程!


本文已通过 CSDN 内容安全检测,无违规信息。
代码仅供学习,请勿用于商业采集或违反网站条款的行为。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 17:04:44

系统思考:海外战略辅导团队学习

今日的海外战略辅导学习,我借用了新加坡口福集团庞琳大哥在《烟火岁月自在行》第六章中的一个案例作为开场——口福集团是如何一步步打造出真正的学习型组织,并在十多年里每年都保持双位数增长的。 书中也提到,在发展过程中,口福集…

作者头像 李华
网站建设 2026/5/28 21:35:56

Java毕设项目:基于springboot的中药科普知识平台的设计与实现(源码+文档,讲解、调试运行,定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/5/29 22:27:41

【金融项目实战】11_接口测试 _代码(python+flask)实现mock服务

文章目录一、代码实现mock服务1.1 flask基本用法二、模拟状态码[面试题]一、代码实现mock服务 需求场景: 模拟一个:登录接口-1、在API文档中说明如果登录成功,返回:状态码:200 {"status":200,"msg":"登录成功!","token":…

作者头像 李华
网站建设 2026/5/29 0:16:12

浙江大学首创手机AI助手“记忆力大考“

这项由浙江大学牵头,联合南开大学、香港中文大学、上海交通大学及vivo AI实验室共同完成的重要研究发表于2026年2月,为人工智能领域的手机助手评测提供了全新视角。有兴趣深入了解的读者可以通过arXiv:2602.06075查询完整论文。当你使用手机上的AI助手时…

作者头像 李华
网站建设 2026/5/28 20:44:13

南大团队突破:AI实现多语言推理完美一致性

这项由南京大学新型软件技术国家重点实验室、德国图宾根大学和中国移动研究院联合开展的突破性研究,于2026年2月发表在arXiv预印本平台(论文编号:arXiv:2602.05940v1)。研究团队发现了多语言AI推理中一个令人困扰的现象&#xff0…

作者头像 李华
网站建设 2026/5/29 1:34:53

首尔国立大学等机构突破:AI实现数学答案自动对错判断

这项由首尔国立大学领导、联合OnelineAI和ORACLE等多家机构共同完成的研究,发表于2026年2月的预印本论文(arXiv:2602.06291v1),为我们揭开了一个颇为有趣的科学谜题:当人工智能面对那些连自己都解不出来的高难度数学问…

作者头像 李华