用于大容量 Web 抓取的 Python 线程与 Gevent

Posted

技术标签:

【中文标题】用于大容量 Web 抓取的 Python 线程与 Gevent【英文标题】:Python Threading vs Gevent for High Volume Web Scraping 【发布时间】:2018-02-04 14:02:08 【问题描述】:

我正在尝试决定是否应该使用 gevent 或线程在 python 中实现 web 抓取的并发性。

我的程序应该能够支持大量(~1000)并发工作人员。大多数时候,工作人员会等待请求返回。

一些指导性问题: 线程和greenlet之间到底有什么区别?我应该在单个进程中创建的最大线程数是多少(关于服务器的规范)?

【问题讨论】:

太宽泛了?如果您有多个问题,请提出多个问题。 我认为你也应该考虑 asyncio。为了回答您的问题,greenlet 通常比普通线程的重量更轻,这意味着创建许多线程和在它们之间切换的开销更少。然而,因此它们之间共享更多,在某些情况下,这可能是一个问题。您确实需要查看更长的教程才能获得更好的想法。 【参考方案1】:

我认为你没有考虑过这整件事。我已经使用从 Gevent 框架创建的 Greenlets 完成了一些相当轻量级的线程应用程序。只要您允许控制在具有适当睡眠或开关的 Greenlets 之间切换 - 一切都会正常工作。建议不要阻塞或等待回复,而是等待或阻塞超时,引发并除外,然后休眠(在代码的除外部分中),然后再次循环 - 否则您将不会轻易切换 Greenlets。

此外,请注意加入和/或杀死所有 Greenlets,因为您最终可能会遇到僵尸,导致您不想要的大量效果。

但是,我不建议您将其用于您的应用程序。相反,以下使用 Gevent 的 Websockets 扩展之一...查看此链接

Websockets in Flask

还有这个链接

https://www.shanelynn.ie/asynchronous-updates-to-a-webpage-with-flask-and-socket-io/

我用 Flask-SocketIO 实现了一个非常不错的应用程序

https://flask-socketio.readthedocs.io/en/latest/

它在 Docker 容器中非常好地通过 Gunicorn 和 nginx 运行。 SocketIO 与客户端的 javascript 接口非常好。

(小心网络抓取 - 使用 Scrapy 之类的东西并启用适当的道德抓取)

【讨论】:

【参考方案2】:

python 线程是由操作系统控制的操作系统线程,这意味着它要重得多,因为它需要上下文切换,但绿色线程是轻量级的,因为它在用户空间中,操作系统不会创建或管理它们。 我认为您可以使用geventGevent = eventloop(libev) + coroutine(greenlet) + monkey patch、Gevent 为您提供线程,但不使用线程,您可以编写普通代码但具有异步 IO。 确保你的代码中没有 CPU 绑定的东西。

【讨论】:

以上是关于用于大容量 Web 抓取的 Python 线程与 Gevent的主要内容,如果未能解决你的问题,请参考以下文章

scrapy和python有啥关系

Python零基础入门爬虫原理与数据抓取--HTTP的请求与响应

python用于啥方向

scrapy

python之爬虫

Python-Scrapy框架