python - 使用 Python 多处理加速抓取?
问题描述
我正在编写一个脚本,该脚本使用该模块从 Reddit 中刮取评论,并使用frompraw
对刮取的内容应用情绪分析。这是我的功能:SentimentIntensityAnalyzer
nltk.sentiment
def analyze_keyword_reddit(keywords):
results = reddit.subreddit("all").search(keywords, sort="comments", limit=None)
all_posts = ""
all_comments = 0
all_upvotes = 0
for post in results:
all_comments += post.num_comments
all_upvotes += post.score
# get all posts for keyword
submission = reddit.submission(id=post.id)
submission.comments.replace_more(limit=0, threshold=10)
posts = " ".join([post.body.lower() for post in submission.comments.list()])
all_posts = all_posts + " " + posts
polarity_scores = sia.polarity_scores(all_posts)
return {**{'all_comments': all_comments, 'all_upvotes': all_upvotes}, **polarity_scores}
在分析这个函数的运行时间时,超过 90% 的运行时间发生在展平评论树的步骤(这一行:)submission.comments.replace_more(limit=0, threshold=5)
。遗憾的是,我还没有发现太多关于此命令的运行时间是否可以显着改善(除了设置threshold
参数并因此限制检索到的评论数量),因此我开始探索多处理选项。使用上面的函数,我运行了以下命令:
if __name__ == '__main__':
tic = time.time()
with multiprocessing.Pool() as p:
print(p.starmap(analyze_keyword_reddit, ['$u unity stock','$fsly fastly stock','$ttcf tattooed chef stock']))
toc = time.time()
然后,为了比较,我还运行了以下一个没有多处理:
tic = time.time()
for t in ['$u unity stock','$fsly fastly stock','$ttcf tattooed chef stock']:
print(analyze_keyword_reddit(t))
toc = time.time()
print(f"Scraping without multiprocessing: {round(toc-tic,2)} seconds.")
普通版耗时 128 秒。然而,多处理版本似乎创建了四个线程,并行评估完全相同的输入四次(当我添加一个简单的print(keywords)
into时,这一点变得很明显analyze_keyword_reddit()
)。这四个线程分别花费了 708、727、729 和 731 秒。此外,多处理片段似乎仍处于无限循环中 - 它并没有在第三个关键字的末尾停止。
我的实施哪里错了?我的目标是加快抓取过程,我是否走在正确的轨道上,还是应该完全采用另一种实现方式?
编辑:
根据下面 Ron Serruya 的精彩回复,我更新了现在使用的代码,map()
而不是starmap()
:
if __name__ == '__main__':
tic = time.time()
with Pool() as p:
print(p.map(analyze_keyword_reddit, ['$u unity stock','$fsly fastly stock','$ttcf tattooed chef stock']))
toc = time.time()
print(f"Scraping with multiprocessing: {round(toc-tic,2)} seconds.")
然而,这一次这个过程似乎还没有开始。该功能analyze_keyword_reddit
似乎永远不会被评估。我在它的开头添加了一个打印功能,终端上根本没有输出。
解决方案
尝试使用map
而不是starmap
Starmap 期望 args 是可迭代的,然后将可迭代解包到函数中
所以p.starmap(analyze_keyword_reddit, ["hello", "world"])
会打电话analyze_keyword_reddit(['h','e','l','l','o'])
给analyze_keyword_reddit(['w','o','r','l','d'])
我可以假设它使 Reddit 库更努力地工作
In [1]: from multiprocessing import Pool
In [2]: with Pool() as p:
...: p.starmap(print, ["hello", "world"])
...:
h e l l o
w o r l d
In [3]: with Pool() as p:
...: p.map(print, ["hello", "world"])
...:
hello
world
推荐阅读
- javascript - 如何使用javascript或react检查touchevent是否存在?
- python - Tiktok Webscraping 使用 Beautifulsoup,但没有从频道获取视频 url 或视频 id
- python - 我可以将列表中的 2 个连续空字符串合并为 1 个空字符串,这样当我们有 4 个空字符串时,它应该合并并生成 2 个空字符串
- php - laravel + react 不使用 localhost 加载 React 的东西(没有 php artisan serve)
- spring-boot - Spring Boot logback-spring.xml 在路径 /var/log 下创建一个日志文件,即使在 xml 和 application.properties 文件中定义了自定义日志路径
- .net-core - 验证注解 - 实体框架核心
- flutter - 无法升级 Flutter:未配置源存储库
- c# - 字符串值不能通过类方法赋值
- python - 在 Heroku 生产期间如何处理 google 服务帐户 json 文件
- isabelle - Isabelle/HOL 中权利取消的定义