【发布时间】:2019-01-12 03:18:25
【问题描述】:
我正在尝试学习如何使用 Python 的 asyncio 模块同时运行任务。在下面的代码中,我有一个模拟的“网络爬虫”作为示例。基本上,我试图让它在任何给定时间最多有两个活动的 fetch() 请求发生,并且我希望在 sleep() 期间调用 process()。
import asyncio
class Crawler():
urlq = ['http://www.google.com', 'http://www.yahoo.com',
'http://www.cnn.com', 'http://www.gamespot.com',
'http://www.facebook.com', 'http://www.evergreen.edu']
htmlq = []
MAX_ACTIVE_FETCHES = 2
active_fetches = 0
def __init__(self):
pass
async def fetch(self, url):
self.active_fetches += 1
print("Fetching URL: " + url);
await(asyncio.sleep(2))
self.active_fetches -= 1
self.htmlq.append(url)
async def crawl(self):
while self.active_fetches < self.MAX_ACTIVE_FETCHES:
if self.urlq:
url = self.urlq.pop()
task = asyncio.create_task(self.fetch(url))
await task
else:
print("URL queue empty")
break;
def process(self, page):
print("processed page: " + page)
# main loop
c = Crawler()
while(c.urlq):
asyncio.run(c.crawl())
while c.htmlq:
page = c.htmlq.pop()
c.process(page)
但是,上面的代码会一个一个地下载 URL(不是一次同时下载两个),并且在获取所有 URL 之前不会进行任何“处理”。如何使 fetch() 任务同时运行,并使其在 sleep() 期间调用 process()?
【问题讨论】:
-
我的最终目标是编写一个异步网络爬虫,它将在后台不断地从 URL 队列中获取页面,HTML/文本处理与获取同时发生。这只是学习使用 asyncio 的模拟代码......这就是为什么我试图在获取的同时运行处理,而不是在之后才这样做。
-
运行事件循环是一个阻塞操作。你需要让
process成为一个协同程序,它会被循环调度或被其他东西等待。
标签: python asynchronous concurrency task python-asyncio