3

我有 5,00,000 个网址。并希望获得每个异步的响应。

import aiohttp
import asyncio    

@asyncio.coroutine
def worker(url):
    response = yield from aiohttp.request('GET', url, connector=aiohttp.TCPConnector(share_cookies=True, verify_ssl=False))
    body = yield from response.read_and_close()

    print(url)

def main():
    url_list = [] # lacs of urls, extracting from a file

    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([worker(u) for u in url_list]))

main()

我一次想要 200 个连接(并发 200),不超过这个,因为

当我为 50 个 url 运行该程序时,它工作正常,即,url_list[:50] 但如果我通过整个列表,我会收到此错误

aiohttp.errors.ClientOSError: Cannot connect to host www.example.com:443 ssl:True Future/Task exception was never retrieved future: Task()

可能是频率太多,服务器在限制后拒绝响应?

4

1 回答 1

6

是的,可以预期服务器在对其造成过多流量(无论“过多流量”的定义如何)后停止响应。

在这种情况下限制并发请求数量(限制它们)的一种方法是使用asyncio.Semaphore,与多线程中使用的请求类似:就像那里一样,您创建一个信号量并确保要限制的操作是先获取该信号量做实际工作并在之后发布。

为了您的方便,asyncio.Semaphore实现上下文管理器使其更容易。

最基本的方法:

CONCURRENT_REQUESTS = 200


@asyncio.coroutine
def worker(url, semaphore):
    # Aquiring/releasing semaphore using context manager.
    with (yield from semaphore):
        response = yield from aiohttp.request(
            'GET',
            url,
            connector=aiohttp.TCPConnector(share_cookies=True,
                                           verify_ssl=False))
        body = yield from response.read_and_close()

        print(url)


def main():
    url_list = [] # lacs of urls, extracting from a file

    semaphore = asyncio.Semaphore(CONCURRENT_REQUESTS)
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([worker(u, semaphore) for u in url_list]))    
于 2015-02-09T10:53:13.810 回答