код 429 при использовании aiohttp

мне нужно получить ответ с более чем 600 страниц, однако большинство ответов приходят с ошибкой 429. Я попытался те ответы, которые приходят с 429, снова отправить в задачи, но это тоже не особо помогает.

async def fetch(session: aiohttp.ClientSession, url: str, params: dict) -> str:
    async with session.get(url, headers=headers, params=params) as response:
        global tasks

        if response.status == 429:
            tasks.append(asyncio.create_task(fetch(session, url, params)))
            return

        response = await response.text()
        return response


async def parse_otodom() -> tuple:
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, URL.get('otodom'), {})
        soup = BeautifulSoup(html, 'lxml')

        page_quantity = int(
            soup.find('ul', class_='e1h66krm4 css-iiviho').find_all('li', class_='css-1lclt1h')[-1].text)


        for page_number in range(1, page_quantity + 1):
            tasks.append(asyncio.create_task(fetch(session, URL.get('otodom'), {'page': page_number})))

        global tasks
        global results_number
        for result in await asyncio.gather(*tasks):
            if result != None:
                results_number+=1


asyncio.run(parse_otodom())
print(results_number)

Исключений код не возвращает. Хотя бы подскажите в каком направлении думать и что можно использовать. Спасибо


Ответы (1 шт):

Автор решения: vortexsf24
  1. Нужно было установить максимальное количество одновременных подключений, которых connector разрешит установить. Это нужно, потому что многие веб-серверы имеют ограничения на количество одновременных подключений, которые они разрешают с одного IP-адреса. Это делается так:

    async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=10)) as session:

  2. Идея с добавлением корутин, которые возвращали 429, снова в список tasks была в правильная, однако реализация была неверной. Если просто добавлять задачи, используя tasks.append(asyncio.create_task(fetch(session, url, params))), то эти новые задачи не будут исполняться до нового запуска await asyncio.gather(*tasks). Вместо этого нужно делать так:

    loop = asyncio.get_event_loop()

    await loop.create_task(fetch(session, URL.get('otodom'), params))

    Тогда только что созданные задачи будут исполнены.

→ Ссылка