【发布时间】:2019-05-29 15:09:36
【问题描述】:
我正在为我的 SPA 应用程序编写爬虫程序。由于它是一个 SPA,我不能使用 wget/curl 或任何其他基于非浏览器的解决方案进行抓取,因为我需要一个浏览器才能在我的 SPA 中运行 javascript。
我使用 python 和 selenium 对此进行了编码。它将从主页开始,扫描所有 href 元素,将它们保存在 set 中,丢弃我已经访问过的那些(visited 和 opened with selenium and collected all the href elements 一样),然后从集合中获取下一个 URL并参观它。然后它将一遍又一遍地重复该过程,直到它访问了所有链接。
代码如下所示:
def main():
...
# Here we will be saving all the links that we can find in the DOM of
# each visited URL
collected = set()
collected.add(crawler.start_url)
# Here we will be saving all the URLs that we have already visited
visited = set()
base_netloc = urlparse(crawler.start_url).netloc
while len(collected):
url = collected.pop()
urls = self.collect_urls(url)
urls = [x for x in urls if x not in visited and urlparse(x).netloc == base_netloc]
collected = collected.union(urls)
visited.add(url)
crawler.links = list(visited)
crawler.save()
def collect_urls(self, url):
browser = Browser()
browser.fetch(url)
urls = set()
elements = browser.get_xpath_elements("//a[@href]")
for element in elements:
link = browser.get_element_attribute(element, "href")
if link != url:
urls.add(link)
browser.stop()
return urls
我希望每次调用collect_urls 时都调用一个 Celery 任务,这样它可以在失败时重试,并且还可以加快整个过程(使用多个工作人员)。问题是collect_urls 是从while 内部调用的,这取决于collected 集合,该集合由collect_urls 的结果填充。
我知道我可以使用 delay() 调用 Celery 任务并使用 get() 等待结果,因此我的代码将如下所示:
while len(collected):
url = collected.pop()
task = self.collect_urls.delay(url)
urls = task.get(timeout=30)
这会将我对 collect_urls 的调用转换为 Celery 任务,如果出现故障,我可以重试,但我仍然无法使用多个工人,因为我需要等待结果的delay()。
我怎样才能重构我的代码,让我可以为collect_urls 使用多个工作人员?
【问题讨论】:
标签: python django python-3.x selenium celery