我有一个同步请求大约 30 个 url 的抓取脚本。完成所有请求需要 95s。
我已经使用异步库
asyncio
和 aiohttp
重写了脚本以提高速度。
这里是 32 个请求的性能统计:
我认为速度提高 50% 是非常糟糕的,所以我试图怀疑我的请求并不是真正的异步触发(我是新手
asyncio
)。
事实上,由于单个请求只需要 1 秒,而我只发出 32 个请求,因此我预计我的异步请求总时间少于 1.5 秒。 32 个请求很少,所以我假设它们几乎同时开始,所以等待最后一个完成的时间不应超过 1.5 秒。
我会很感激任何提示。
# Single asynchronous request
async def async_get_course(session, url_course):
async with session.get(url_course) as res:
response = await res.content.read()
return response
# Main coroutine
async def example(courses, root):
starting_time = time.time()
actions = []
data = []
data2 = []
async with aiohttp.ClientSession() as session:
for course in courses:
url_course = f"{root}{course['course_link']}"
data.append(url_course)
actions.append(asyncio.ensure_future(async_get_course(session, url_course)))
results = await asyncio.gather(*actions)
for idx, res in enumerate(results):
data2.append(get_info_from_course((courses[idx], data[idx], res)))
total_time = time.time() - starting_time
print('total_time', total_time)
return data2
# Run the coroutine
courses_final = asyncio.run(example(courses, root))
您的操作将同时执行:
await asyncio.gather(*actions)
所以你做的一切都是正确的,你正在运行异步和并发代码。您的请求不会同时开始。当另一个请求被阻塞时,事件循环将再处理一个请求。这并不意味着您的策略不好,一般来说,使用 asyncio 来处理 I/O 繁重的操作非常有帮助。您可以尝试将您的操作拆分为 several processes 并且仍然使用 asyncio。