Как использовать asyncio и aiohttp для зацикливания вместо зацикливания? - PullRequest
2 голосов
/ 10 июня 2019

Мой код работает таким образом, но его скорость очень низкая из-за циклов for, можете ли вы помочь мне заставить его работать с aiohttp, asyncio?

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)

1 Ответ

2 голосов
/ 10 июня 2019

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())
...