Python 以每分钟硬限制并行化对API的调用

Python 以每分钟硬限制并行化对API的调用,python,async-await,aiohttp,Python,Async Await,Aiohttp,我正在尝试对API进行并行化调用。API在停止前每分钟有1200个调用的限制。在低于限制的情况下,什么是最有效的异步方式 def remove_html_tags(text): """Remove html tags from a string""" import re clean = re.compile('<.*?>') return re.sub(clean, ' ', text) async def getRez(df, url): asyn

我正在尝试对API进行并行化调用。API在停止前每分钟有1200个调用的限制。在低于限制的情况下,什么是最有效的异步方式

def remove_html_tags(text):
    """Remove html tags from a string"""
    import re
    clean = re.compile('<.*?>')
    return re.sub(clean, ' ', text)

async def getRez(df, url):
async with aiohttp.ClientSession() as session:
        auth = aiohttp.BasicAuth('username',pwd)


        r = await session.get(url, auth=auth)


        if r.status == 200:
            content = await r.text()
            text = remove_html_tags(str(content))

        else:
            text = '500 Server Error'
        df.loc[df['url'] == url, ['RezText']] = [[text]]
        df['wordCount'] = df['RezText'].apply(lambda x: len(str(x).split(" ")))
        data = df[df["RezText"] != "500 Server Error"]


async def main(df):
    df['RezText'] = None
    await asyncio.gather(*[getRez(df, url) for url in df['url']])

loop = asyncio.get_event_loop()
loop.run_until_complete(main(data))
def删除html标签(文本):
“”“从字符串中删除html标记”“”
进口稀土
clean=re.compile(“”)
返回re.sub(干净,,,文本)
异步def getRez(df,url):
与aiohttp.ClientSession()作为会话异步:
auth=aiohttp.BasicAuth('username',pwd)
r=wait session.get(url,auth=auth)
如果r.status==200:
content=wait r.text()
text=删除html标记(str(内容))
其他:
text='500服务器错误'
df.loc[df['url']==url,['RezText']]=[[text]]
df['wordCount']=df['RezText'].apply(lambda x:len(str(x).split(“”))
数据=df[df[“RezText”]!=“500服务器错误”]
异步def主(df):
df['RezText']=无
等待asyncio.gather(*[getRez(df,url)获取df['url']]中的url)
loop=asyncio.get\u event\u loop()
循环。运行_直到_完成(主(数据))

每分钟1200次呼叫等于每秒20次呼叫,因此您可以将请求分成20次批,并在批之间休眠一秒钟

另一种选择是在客户端会话中使用
aiohttp.TCPConnector(limit=20)
,但这只会限制并发请求的数量,因此最终可能会执行更多请求(如果API响应速度超过1秒)或更少请求(如果API响应速度低于1秒);见相关问题

批处理示例:

#python 3.7+
进口aiohttp
导入异步
异步def提取(会话,url):
数据=无
以session.get(url)作为响应的异步:
如果响应.status!=200:
text=等待响应。text()
打印(“无法检索%s:状态:%d,原因:%s”%(url,response.status,text))
其他:
data=wait response.json()
返回数据
异步def主(n):
打印(“开始”)
session=aiohttp.ClientSession()
任务=[]
批次=[]
对于范围(n)中的i:
批处理。追加(“http://httpbin.org/anything?key=a%d%i)
如果len(批次)>=20:
打印(“发布批次%d:%d”%(i-20+1,i+1))
对于批量url:
task=asyncio.create_任务(获取(会话,url))
tasks.append(任务)
批次=[]
等待asyncio.sleep(1)
如果批次:#如果批次长度未平均除以n,则消耗最后一批
打印(“发布最后一批%d:%d”%(n-len(批),n))
对于批量url:
task=asyncio.create_任务(获取(会话,url))
附加(获取(会话,url))
responses=wait asyncio.gather(*任务,返回\u异常=True)
等待会话。关闭()
关于答复中的答复:
在响应中断言“args”
#请注意,响应将按照请求的顺序进行
打印(“完成”)
如果名称=“\uuuuu main\uuuuuuuu”:
loop=asyncio.get\u event\u loop()
循环。运行_直到_完成(主(111))
输出

starting
issuing batch 0:20
issuing batch 20:40
issuing batch 40:60
issuing batch 60:80
issuing batch 80:100
issuing last batch 100:111
finished
这里的重要部分是
asyncio.create_task
(创建任务并启动它,返回任务对象)、
wait asyncio.sleep(1)
(用于限制请求)和
wait asyncio.gather
(等待所有任务完成运行)。
对于Python<3.7,您可以使用
asyncio。确保未来
而不是
asyncio。创建任务