【问题标题】:How to use asyncio and aiohttp for looping instead of for looping?如何使用 asyncio 和 aiohttp 循环而不是循环?
【发布时间】:2019-06-10 15:02:05
【问题描述】:

我的代码以这种方式工作,但由于 for 循环,它的速度非常慢,你能帮我,使它与 aiohttpasyncio 一起工作吗?

def field_info(field_link):
    response = requests.get(field_link)
    soup = BeautifulSoup(response.text, 'html.parser')
    races = soup.findAll('header', {'class': 'dc-field-header'})
    tables = soup.findAll('table', {'class': 'dc-field-comp'})

    for i in range(len(races)):
        race_name = races[i].find('h3').text
        race_time = races[i].find('time').text

        names = tables[i].findAll('span', {'class': 'title'})
        trainers = tables[i].findAll('span', {'class': 'trainer'})
        table = []

        for j in range(len(names)):
            table.append({
                'Name': names[j].text,
                'Trainer': trainers[j].text,
            })

        return {
                'RaceName': race_name,
                'RaceTime': race_time,
                'Table': table
                }


links = [link1, link2, link3]
for link in links:
    scraped_info += field_info(link)

【问题讨论】:

  • 为什么? asyncioaiohttp 都不会为您的代码提供神奇的并行性,也不会加速 CPU 密集型任务。它们适用于异步编程
  • 这与您的问题无关,但您可以使用for name, trainer in zip(names, trainers),而不是使用range(len(names)),并避免循环内的索引查找。

标签: python-3.x web-scraping python-asyncio aiohttp


【解决方案1】:

1) 创建协程以异步发出请求:

import asyncio
import aiohttp


async def get_text(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            return await resp.text()

2) 将所有同步请求替换为等待这个协程,使外部函数也成为协程:

async def field_info(field_link):              # async - to make outer function coroutine
    text = await get_text(field_link)          # await - to get result from async funcion
    soup = BeautifulSoup(text, 'html.parser')

3) 使用asyncio.gather() 制作外部代码同时执行工作:

async def main():
    links = [link1, link2, link3]

    scraped_info = asyncio.gather(*[
        field_info(link)
        for link
        in links
    ])  # do multiple field_info coroutines concurrently (parallely)

4) 将顶级协程传递给asyncio.run()

asyncio.run(main())

【讨论】:

  • 感谢您一步一步的回答,它确实帮助我了解了这些东西是如何工作的。
  • @paskh 不客气!您可能也有兴趣阅读 this answer - 它是关于 asyncio 的工作原理以及一般如何使用它。
猜你喜欢
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多