Очистка контента с использованием pyppeteer в сочетании с asyncio

Я написал скрипт на Python в сочетании с pyppeteer вместе с asyncio очистить ссылки на различные посты со своей целевой страницы и в конечном итоге получить заголовок каждого поста, отслеживая URL, ведущий к его внутренней странице. Контент, который я здесь проанализировал, не является динамическим. Тем не менее, я использовал pyppeteer а также asyncio чтобы увидеть, насколько эффективно это работает asynchronously,

Следующий сценарий подходит для некоторых моментов, но затем выдает ошибку:

File "C:\Users\asyncio\tasks.py", line 526, in ensure_future
raise TypeError('An asyncio.Future, a coroutine or an awaitable is '
TypeError: An asyncio.Future, a coroutine or an awaitable is required

Это то, что я написал до сих пор:

import asyncio
from pyppeteer import launch

link = "https://stackru.com/questions/tagged/web-scraping"

async def fetch(page,url):
    await page.goto(url)
    linkstorage = []
    elements = await page.querySelectorAll('.summary .question-hyperlink')
    for element in elements:
        linkstorage.append(await page.evaluate('(element) => element.href', element))
    tasks = [await browse_all_links(link, page) for link in linkstorage]
    results = await asyncio.gather(*tasks)
    return results

async def browse_all_links(link, page):
    await page.goto(link)
    title = await page.querySelectorEval('.question-hyperlink','(e => e.innerText)')
    print(title)

async def main(url):
    browser = await launch(headless=True,autoClose=False)
    page = await browser.newPage()
    await fetch(page,url)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    future = asyncio.ensure_future(main(link))
    loop.run_until_complete(future)
    loop.close()

Мой вопрос: как я могу избавиться от этой ошибки и делать асинхронно?

1 ответ

Решение

Проблема в следующих строках:

tasks = [await browse_all_links(link, page) for link in linkstorage]
results = await asyncio.gather(*tasks)

Намерение для tasks быть списком ожидаемых объектов, таких как объекты сопрограммы или фьючерсы. Список должен быть передан gather, так что ожидаемые могут работать параллельно, пока они все не завершены. Однако, понимание списка содержит ожидание, что означает, что оно:

  • выполняет каждый browser_all_links до завершения последовательно, а не параллельно;
  • помещает возвращаемые значения browse_all_links вызовы в список.

поскольку browse_all_links не возвращает значение, вы передаете список None возражает против asyncio.gather, который жалуется, что не получил ожидаемый объект.

Чтобы решить проблему, просто бросьте await из списка понимания.

Другие вопросы по тегам