使用与 asyncio 关联的 pyppeteer 抓取内容
Scraping content using pyppeteer in association with asyncio
我在 python 中编写了一个脚本,结合 pyppeteer
和 asyncio
从其着陆页中抓取不同 post 的链接,并最终通过跟踪通向其内页的 url 获取每个 post 的标题。我这里解析的内容不是动态的。但是,我使用 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://whosebug.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()
我的问题:如何消除该错误并异步执行操作?
问题出在以下几行:
tasks = [await browse_all_links(link, page) for link in linkstorage]
results = await asyncio.gather(*tasks)
目的是让 tasks
成为可等待对象的列表,例如协程对象或期货。该列表将被传递给 gather
,以便等待对象可以并行 运行,直到它们全部完成。但是,列表理解包含一个 await,这意味着它:
- 执行每个
browser_all_links
以完成 串行 而不是并行;
- 将
browse_all_links
个调用的 return 值 放入列表中。
由于 browse_all_links
没有 return 值,您将 None
对象的列表传递给 asyncio.gather
,它抱怨它没有得到一个等待对象。
要解决此问题,只需从列表理解中删除 await
。
我在 python 中编写了一个脚本,结合 pyppeteer
和 asyncio
从其着陆页中抓取不同 post 的链接,并最终通过跟踪通向其内页的 url 获取每个 post 的标题。我这里解析的内容不是动态的。但是,我使用 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://whosebug.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()
我的问题:如何消除该错误并异步执行操作?
问题出在以下几行:
tasks = [await browse_all_links(link, page) for link in linkstorage]
results = await asyncio.gather(*tasks)
目的是让 tasks
成为可等待对象的列表,例如协程对象或期货。该列表将被传递给 gather
,以便等待对象可以并行 运行,直到它们全部完成。但是,列表理解包含一个 await,这意味着它:
- 执行每个
browser_all_links
以完成 串行 而不是并行; - 将
browse_all_links
个调用的 return 值 放入列表中。
由于 browse_all_links
没有 return 值,您将 None
对象的列表传递给 asyncio.gather
,它抱怨它没有得到一个等待对象。
要解决此问题,只需从列表理解中删除 await
。