Python爬取知乎评论:多线程与异步爬虫的性能优化

1. 知乎评论爬取的技术挑战

知乎的评论数据通常采用动态加载(Ajax),这意味着直接使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">requests</font>**+**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">BeautifulSoup</font>**无法获取完整数据。此外,知乎还设置了反爬机制,包括:

  • 请求头(Headers)验证(如**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">User-Agent</font>****<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Referer</font>**
  • Cookie/Session 校验(未登录用户只能获取部分数据)
  • 频率限制(频繁请求可能导致IP被封)

因此,我们需要:

  1. 模拟浏览器请求(携带Headers和Cookies)
  2. 解析动态API接口(而非静态HTML)
  3. 优化爬取速度(多线程/异步)

2. 获取知乎评论API分析

(1)查找评论API

打开知乎任意一个问题(如 **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">https://www.zhihu.com/question/xxxxxx</font>**),按**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">F12</font>**进入开发者工具,切换到**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Network</font>**选项卡,筛选**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">XHR</font>**请求

(2)解析评论数据结构

评论通常嵌套在**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">data</font>**字段中,结构如下:

{"data": [{"content": "评论内容","author": { "name": "用户名" },"created_time": 1620000000}],"paging": { "is_end": false, "next": "下一页URL" }
}

我们需要递归翻页(**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">paging.next</font>**)爬取所有评论。

3. Python爬取知乎评论的三种方式

(1)单线程爬虫(基准测试)

使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">requests</font>**库直接请求API,逐页爬取:

import requests
import timedef fetch_comments(question_id, max_pages=5):base_url = f"https://www.zhihu.com/api/v4/questions/{question_id}/answers"headers = {"User-Agent": "Mozilla/5.0","Cookie": "你的Cookie"  # 登录后获取}comments = []for page in range(max_pages):url = f"{base_url}?offset={page * 10}&limit=10"resp = requests.get(url, headers=headers).json()for answer in resp["data"]:comments.append(answer["content"])time.sleep(1)  # 避免请求过快return commentsstart_time = time.time()
comments = fetch_comments("12345678")  # 替换为知乎问题ID
print(f"单线程爬取完成,耗时:{time.time() - start_time:.2f}秒")

缺点:逐页请求,速度慢(假设每页1秒,10页需10秒)。

(2)多线程爬虫(ThreadPoolExecutor)

使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">concurrent.futures</font>**实现多线程并发请求:

from concurrent.futures import ThreadPoolExecutordef fetch_page(page, question_id):url = f"https://www.zhihu.com/api/v4/questions/{question_id}/answers?offset={page * 10}&limit=10"headers = {"User-Agent": "Mozilla/5.0"}resp = requests.get(url, headers=headers).json()return [answer["content"] for answer in resp["data"]]def fetch_comments_multi(question_id, max_pages=5, threads=4):with ThreadPoolExecutor(max_workers=threads) as executor:futures = [executor.submit(fetch_page, page, question_id) for page in range(max_pages)]comments = []for future in futures:comments.extend(future.result())return commentsstart_time = time.time()
comments = fetch_comments_multi("12345678", threads=4)
print(f"多线程爬取完成,耗时:{time.time() - start_time:.2f}秒")

优化点

  • 线程池控制并发数(避免被封)
  • 比单线程快约3-4倍(4线程爬10页仅需2-3秒)

(3)异步爬虫(Asyncio + aiohttp)

使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">aiohttp</font>**实现异步HTTP请求,进一步提高效率:

import aiohttp
import asyncio
import time# 代理配置
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"async def fetch_page_async(session, page, question_id):url = f"https://www.zhihu.com/api/v4/questions/{question_id}/answers?offset={page * 10}&limit=10"headers = {"User-Agent": "Mozilla/5.0"}async with session.get(url, headers=headers) as resp:data = await resp.json()return [answer["content"] for answer in data["data"]]async def fetch_comments_async(question_id, max_pages=5):# 设置代理连接器proxy_auth = aiohttp.BasicAuth(proxyUser, proxyPass)connector = aiohttp.TCPConnector(limit=20,  # 并发连接数限制force_close=True,enable_cleanup_closed=True,proxy=f"http://{proxyHost}:{proxyPort}",proxy_auth=proxy_auth)async with aiohttp.ClientSession(connector=connector) as session:tasks = [fetch_page_async(session, page, question_id) for page in range(max_pages)]comments = await asyncio.gather(*tasks)return [item for sublist in comments for item in sublist]if __name__ == "__main__":start_time = time.time()comments = asyncio.run(fetch_comments_async("12345678"))  # 替换为知乎问题IDprint(f"异步爬取完成,耗时:{time.time() - start_time:.2f}秒")print(f"共获取 {len(comments)} 条评论")

优势

  • 无GIL限制,比多线程更高效
  • 适合高并发IO密集型任务(如爬虫)

4. 性能对比与优化建议

爬取方式10页耗时(秒)适用场景
单线程~10少量数据,简单爬取
多线程(4线程)~2.5中等规模,需控制并发
异步(Asyncio)~1.8大规模爬取,高并发需求

优化建议

  1. 控制并发数:避免触发反爬(建议10-20并发)。
  2. 随机延迟**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">time.sleep(random.uniform(0.5, 2))</font>** 模拟人类操作。
  3. 代理IP池:防止IP被封(如使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">requests</font>**+**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">ProxyPool</font>**)。
  4. 数据存储优化:异步写入数据库(如**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">MongoDB</font>****<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">MySQL</font>**)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/87932.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/87932.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件系统测试的基本流程

软件系统测试流程是确保软件质量的规范化过程&#xff0c;涵盖从测试准备到最终上线评估的全周期&#xff0c;通常分为以下6个核心阶段&#xff0c;各阶段紧密衔接、形成闭环&#xff1a; 一、测试启动与规划阶段 核心目标&#xff1a;明确“测什么、谁来测、怎么测”&#xff…

使用Linux操作MySQL数据库分批导出数据为.SQL文件

当数据库某张数据量非常大的表进行其他操作&#xff0c;需要先进行导出时&#xff1b; 先用linux进入操作环境&#xff0c; 1.添加一个export_mysql_batches.sh脚本文件&#xff0c; #!/bin/bash# 数据库连接配置 DB_HOST"36.33.0.138:3306" DB_USER"devuser&qu…

LeetCode 算法题解:链表与二叉树相关问题 打打卡

LeetCode 算法题解&#xff1a;链表与二叉树相关问题 在算法学习和实践中&#xff0c;LeetCode 是一个非常好的平台&#xff0c;它包含了各种各样的算法题目&#xff0c;有助于我们提升编程能力和解决问题的能力。本文将详细讲解在 leetcoding.cpp 文件中实现的一些链表和二叉树…

故宫票价监控接口分析(一)

故宫票价监控接口分析(一) 对爬虫、逆向感兴趣的同学可以查看文章,一对一小班教学(系统理论和实战教程)、提供接单兼职渠道:https://blog.csdn.net/weixin_35770067/article/details/142514698 本文内容仅供学习和参考之用,不得用于商业目的。作者对文中内容的准确性、完整…

AWS OpenSearch Dev Tools使用

# 创建通用索引模版 PUT _template/aws-waf_logs_template {"index_patterns": ["aws-waf-logs-*"],"mappings": {"properties": {"timestamp": {"type": "date"}}} }# 设置单个索引格式 PUT /aws-waf-…

git-安装 Gerrit Hook 自动生成changeid

要在 Git 中安装 Gerrit Hook 以自动生成 Change-ID&#xff0c;可以按照以下步骤操作&#xff1a; 全局钩子配置&#xff08;推荐&#xff09; 创建全局钩子目录并下载 Gerrit 提供的 commit-msg 钩子脚本&#xff0c;确保所有仓库共享该配置&#xff1a; mkdir -p ~/.githook…

Excel 的多线程特性

Excel 本身并不是完全多线程的应用程序&#xff0c;但它在某些操作和功能上支持多线程处理。以下是对 Excel 是否多线程的详细解答&#xff0c;结合你之前提到的 VBA/COM 自动化代码和受保护视图问题&#xff0c;提供清晰且准确的分析。 Excel 的多线程特性计算引擎的多线程支持…

【嵌入式ARM汇编】-操作系统基础(一)

操作系统基础(一) 文章目录 操作系统基础(一)1、操作系统架构概述2、用户模式与内核模式3、进程4、系统调用5、对象和句柄我们想要逆向的程序几乎从来不会在真空中执行。相反,程序通常在正在运行的操作系统(例如 Linux、Windows 或 macOS)的上下文中运行。因此,了解这些…

[创业之路-474]:企业经营层 - 小米与华为多维对比分析(2025年视角),以后不要把这两家公司放在同一个维度上 进行比较了

一、行业定位与市场角色不同华为&#xff1a;用技术手段解决行业的难题&#xff0c;顺便赚钱技术驱动型硬科技企业&#xff1a;以通信设备起家&#xff0c;延伸至智能手机、芯片、操作系统&#xff08;鸿蒙&#xff09;、云计算、智能汽车等领域&#xff0c;构建“云-管-端”全…

C#基础篇(06)抽象类与接口详解区别

抽象类是 C# 面向对象编程中的一个重要概念&#xff0c;它介于普通类和接口之间&#xff0c;提供了一种定义部分实现并要求派生类完成其余部分的机制。一、C# 中的抽象类抽象类是 C# 面向对象编程中的一个重要概念&#xff0c;它介于普通类和接口之间&#xff0c;提供了一种定义…

使用Python将PDF转换成word、PPT

在现代企业环境中,文档格式的转换是一项普遍且关键的需求。PDF(Portable Document Format)作为一种最终的、通常不可编辑的“打印”状态格式,被广泛用于分发和归档。然而,内容的创建、协作和修改主要在Microsoft Office套件中进行,特别是Word(DOCX)和PowerPoint(PPTX)…

香港风水(原生)林地的逻辑分类器

风水林是香港的原生林地&#xff0c;由于地处偏远、地形崎岖以及当地居民的信仰&#xff0c;这些林地得以保存完好。在香港&#xff0c;我们可以追溯到1924年的航拍图像记录&#xff0c;这些黑白航拍图像已经帮助我们划分和区分了林地、草地和灌木丛。然后&#xff0c;通过二战…

[Swarm] Result对象 | 智能体切换 | Response对象 | muduo review

第5章&#xff1a;结果对象 欢迎回到swarm&#xff01; 在上一章第4章&#xff1a;功能中&#xff0c;我们学习了如何通过定义Python功能赋予智能体技能。我们见证了当AI决策调用时&#xff0c;Swarm框架如何执行这些功能。 当前&#xff0c;我们的功能仅返回简单字符串如&q…

[2-02-02].第04节:环境搭建 - Linux搭建ES集群环境

ElasticSearch学习大纲 一、ES集群规划&#xff1a; 关系型数据库&#xff08;比如Mysql&#xff09;非关系型数据库&#xff08;Elasticsearch&#xff09;非关系型数据库&#xff08;Elasticsearch&#xff09;centos7hadoop103192.168.148.3centos7hadoop104192.168.148.4c…

部署并运行Spike-Driven-Transformer或QKFormer

部署并运行Spike-Driven-Transformer或QKFormer 我将指导你如何部署和运行Spike-Driven-Transformer或QKFormer代码,并在CIFAR-10、CIFAR-100和ImageNet-1K数据集上进行训练和测试。 1. 环境准备 首先需要设置Python环境并安装必要的依赖项: # 创建conda环境(推荐) con…

爬虫-request处理POST

1.概念很少在URL写参数&#xff0c;都在form data里面POST 的主要作用是将客户端的数据提交给服务器。这些数据可以是表单输入、文件内容、JSON 数据、XML 数据等等POST 请求携带的数据放在 HTTP 消息的请求体中。这与 GET 请求形成鲜明对比&#xff1a;GET 请求的数据通常附加…

免U盘一键重装系统

免U盘一键重装系统 简单介绍 详细的看GitHub项目首页 GitHub地址 # 下载脚本 curl -O https://cnb.cool/bin456789/reinstall/-/git/raw/main/reinstall.sh || wget -O reinstall.sh $_ # 重装系统 bash reinstall.sh ubuntu # 重启 rebootPS: 重启过程中, 可能需要手动选择r…

自动化一次通过率

自动化测试中的“一次通过率”&#xff08;First-pass Pass Rate&#xff09;​​ 是指自动化测试脚本在首次执行&#xff08;无人工干预、无重试&#xff09;​时&#xff0c;​成功通过的测试用例数占总执行用例数的百分比。​核心概念解析​​​“一次”的含义​​首次运行​…

111111事件

1.抽取 minio 当做文件对象存储服务器&#xff0c;在上面封装一层api&#xff0c;方便操作。 &#xff08;文件上传&#xff0c;指定路径上传&#xff0c;随机命名上传&#xff0c;前端获取token直接传&#xff0c;适合大对象&#xff0c;图片压缩&#xff09; 2.规范整个java项…

Qt的ui文件的编译和使用

Qt中的ui文件编译的类 要么继承 &#xff0c;要么实例化一个变量个人觉得还是继承好点&#xff0c;这样每次调用控件时&#xff0c;不用都要在控件前加上 ui.1 上面使用的是继承的关系&#xff0c;这样就可以直接使用控件.属性&#xff0c;而不用 ui.控件.树形2 QT中UI文件…