13

我正在尝试创建一个脚本,可以同时向一个页面发送超过 1000 个请求。但是请求带有线程(1000)线程的库。似乎在 1 秒内完成了前 50 个左右的请求,而其他 9950 个请求则花费了相当长的时间。我是这样测量的。

def print_to_cmd(strinng):
    queueLock.acquire()
    print strinng
    queueLock.release()

    start = time.time()
    resp = requests.get('http://test.net/', headers=header)
    end = time.time()

    print_to_cmd(str(end-start))

我认为请求库限制了它们的发送速度。

有人知道在 python 中同时发送请求的方法吗?我有一个上传 200mb 的 VPS,所以这不是问题,它与 python 或请求库限制它有关。他们都需要在 1 秒内互相访问网站。

感谢阅读,我希望有人可以提供帮助。

4

3 回答 3

28

我通常发现最好的解决方案是使用像 tornado 这样的异步库。然而,我发现最简单的解决方案是使用 ThreadPoolExecutor。


import requests
from concurrent.futures import ThreadPoolExecutor

def get_url(url):
    return requests.get(url)
with ThreadPoolExecutor(max_workers=50) as pool:
    print(list(pool.map(get_url,list_of_urls)))
于 2016-11-03T00:37:34.903 回答
11

我知道这是一个老问题,但你现在可以使用asyncioand来做到这一点aiohttp

import asyncio
import aiohttp
from aiohttp import ClientSession

async def fetch_html(url: str, session: ClientSession, **kwargs) -> str:
    resp = await session.request(method="GET", url=url, **kwargs)
    resp.raise_for_status()
    return await resp.text()

async def make_requests(url: str, **kwargs) -> None:
    async with ClientSession() as session:
        tasks = []
        for i in range(1,1000):
            tasks.append(
                fetch_html(url=url, session=session, **kwargs)
            )
        results = await asyncio.gather(*tasks)
        # do something with results

if __name__ == "__main__":
    asyncio.run(make_requests(url='http://test.net/'))

您可以阅读有关它的更多信息并在此处查看示例。

于 2019-08-28T09:18:05.803 回答
1

假设您知道自己在做什么,我首先建议您实施带有抖动的退避策略,以防止“可预测的雷击囤积”到您的服务器。也就是说,你应该考虑做一些threading

import threading
class FuncThread(threading.Thread):
    def __init__(self, target, *args):
        self._target = target
        self._args = args
        threading.Thread.__init__(self)

    def run(self):
        self._target(*self._args)

这样你就会做类似的事情

t = FuncThread(doApiCall, url)
t.start()

您的方法 doApiCall 定义如下

def doApiCall(self, url):
于 2016-11-03T00:25:34.013 回答