……

使用asyncio/aiohttp获取多个url并重试失败

我试图用aiohttp包编写一些异步GET请求,并解决了大部分问题,但是我想知道在处理失败(作为异常返回)时的标准方法是什么。在

到目前为止我的代码的总体思路(经过一番尝试和错误之后,我采用了here)方法:

import asyncio
import aiofiles
import aiohttp
from pathlib import Path

with open('urls.txt', 'r') as f:
    urls = [s.rstrip() for s in f.readlines()]

async def fetch(session, url):
    async with session.get(url) as response:
        if response.status != 200:
            response.raise_for_status()
        data = await response.text()
    # (Omitted: some more URL processing goes on here)
    out_path = Path(f'out/')
    if not out_path.is_dir():
        out_path.mkdir()
    fname = url.split("/")[-1]
    async with aiofiles.open(out_path / f'{fname}.html', 'w+') as f:
        await f.write(data)

async def fetch_all(urls, loop):
    async with aiohttp.ClientSession(loop=loop) as session:
        results = await asyncio.gather(*[fetch(session, url) for url in urls],
                return_exceptions=True)
        return results

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    results = loop.run_until_complete(fetch_all(urls, loop))

现在这一切正常了:

正如预期的那样,results变量被填充了None条目,其中对应的URL[即在urls数组变量中的同一索引处,即输入文件urls.txt]中的同一行号被成功请求,相应的文件被写入磁盘。在
这意味着我可以使用results变量来确定哪些url不成功(results中的那些条目不等于None)

我已经看了一些不同的指南来使用各种异步Python包(aiohttp,aiofiles,和asyncio),但是我还没有看到处理这最后一步的标准方法。在

{/'在请求完成后,{cd10>是否应该完成?在
…还是应该在失败时通过某种回调来重新发送GET请求
    错误如下:(ClientConnectorError(111, "Connect call failed ('000.XXX.XXX.XXX', 443)")即在端口443向IP地址000.XXX.XXX.XXX的请求失败,可能是因为服务器有一些限制,我应该在重试之前等待一段时间。在
我是否可以考虑设置某种限制,对请求进行批处理而不是全部尝试?在
当我尝试在我的列表中获得超过100个URL时,我成功地获得了40-500个请求。在

天真地说,我希望^{}以这样一种方式处理此问题,即在成功请求所有URL时完成,但事实并非如此。在

我以前没有使用过异步Python和session/loops,所以希望您能帮助我找到results。请让我知道,如果我能提供更多的信息来改进这个问题,谢谢!在

posted on 2021-03-10 16:08  Exlo  阅读(462)  评论(0编辑  收藏  举报

导航