Python3,Urllib3:对100,000个请求的单个站点的快速服务器友好请求?

时间:2014-10-29 10:13:20

标签: python-3.x urllib3

我试图通过网络API获取整个Old Bailey Online档案的子集。

我的问题是我的实现不仅很慢,而且服务器很快就会停止服务我的请求(大约10分钟)。

目前我正在使用urllib3的开发版本:

import urllib3
retry = urllib3.util.Retry(total=1000, read=200, connect=200, backoff_factor=0.5)
timeout = urllib3.util.Timeout(connect=2.0, read=4.0)
http=urllib3.PoolManager(retry=retry, timeout=timeout, maxsize=10)

然后我用这个http池运行我的所有请求。我选择的数字相当荒谬,但最好的还是8(

每年,我需要提出70个并发请求,超过243年,并针对不同的情况。  我尝试使用@shazow的workerpool(根据https://stackoverflow.com/a/24046895/398969修改为与python3.4一起工作),同时在一年内,多线程年份,这也没有太好用。主要是由于服务器超时和我的无知。

DNS查找引入了明显的延迟吗?我不能使用Ip,因为域是一个apache虚拟主机(或者我可以吗?)

洙。真正的问题:如何“很好地”及时地从同一台服务器上下载数十万次?我仍然期待它需要一天左右的时间8)

1 个答案:

答案 0 :(得分:1)

听起来服务器可能会因过于频繁地提出太多请求而限制/禁止您的IP。

首先,我建议检查域上的robots.txt,看看是否有关于自动请求频率的指导。如果没有,您可以要求网站所有者就如何最好地抓取网站提出建议。否则,您可能需要通过实验确定速率限制。

要限制您的请求,您可以使用apiclient。RateLimiter *(source)之类的内容。它看起来像这样:

from apiclient import RateLimiter
from urllib3 import PoolManager

lock = RateLimiter(max_messages=30, every_seconds=60)
http = PoolManager(...)
...

for url in crawl_list:
    lock.acquire()
    r = http.request(...)

您可以做的另一件事是抓取网站的缓存版本(如果可以通过Google或archive.org访问)。

[*] 免责声明:很久以前我也写过了apiclient。它没有超级记录。我怀疑如果你发现它缺乏,你可以使用其他类似的模块,但源码应该相当容易理解和扩展。