在 Python 中发送 100,000 个 HTTP 请求的最快方法是什么?

新手上路,请多包涵

我正在打开一个包含 100,000 个 URL 的文件。我需要向每个 URL 发送 HTTP 请求并打印状态代码。我正在使用 Python 2.6,到目前为止,我已经了解了 Python 实现线程/并发的许多令人困惑的方式。我什至看过 python 并发 库,但不知道如何正确编写这个程序。有没有人遇到过类似的问题?我想通常我需要知道如何尽可能快地在 Python 中执行数千个任务——我想这意味着“同时”。

原文由 IgorGanapolsky 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 496
2 个回答

无扭曲解决方案:

 from urlparse import urlparse
from threading import Thread
import httplib, sys
from Queue import Queue

concurrent = 200

def doWork():
    while True:
        url = q.get()
        status, url = getStatus(url)
        doSomethingWithResult(status, url)
        q.task_done()

def getStatus(ourl):
    try:
        url = urlparse(ourl)
        conn = httplib.HTTPConnection(url.netloc)
        conn.request("HEAD", url.path)
        res = conn.getresponse()
        return res.status, ourl
    except:
        return "error", ourl

def doSomethingWithResult(status, url):
    print status, url

q = Queue(concurrent * 2)
for i in range(concurrent):
    t = Thread(target=doWork)
    t.daemon = True
    t.start()
try:
    for url in open('urllist.txt'):
        q.put(url.strip())
    q.join()
except KeyboardInterrupt:
    sys.exit(1)

这个比扭曲的解决方案稍微快一点,并且使用更少的 CPU。

原文由 Tarnay Kálmán 发布,翻译遵循 CC BY-SA 3.0 许可协议

自 2010 年发布此内容以来,情况发生了很大变化,我没有尝试所有其他答案,但我尝试了一些,我发现这对我使用 python3.6 最有效。

在 AWS 上运行时,我每秒能够获取约 150 个唯一域。

 import concurrent.futures
import requests
import time

out = []
CONNECTIONS = 100
TIMEOUT = 5

tlds = open('../data/sample_1k.txt').read().splitlines()
urls = ['http://{}'.format(x) for x in tlds[1:]]

def load_url(url, timeout):
    ans = requests.head(url, timeout=timeout)
    return ans.status_code

with concurrent.futures.ThreadPoolExecutor(max_workers=CONNECTIONS) as executor:
    future_to_url = (executor.submit(load_url, url, TIMEOUT) for url in urls)
    time1 = time.time()
    for future in concurrent.futures.as_completed(future_to_url):
        try:
            data = future.result()
        except Exception as exc:
            data = str(type(exc))
        finally:
            out.append(data)

            print(str(len(out)),end="\r")

    time2 = time.time()

print(f'Took {time2-time1:.2f} s')

原文由 Glen Thompson 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题