目前我正在做一个作为API运行的爬虫项目,因此我做了一些关于在HTTP服务器中运行scrapy的研究。为了简单起见,我选择了Python Klein,基本上遵循以下内容:
https://github.com/betinacosta/scrapy-klein-tutorial/blob/master/README%5BEN-US%5D.md
目前,我的代码看起来像这样(Python 3.9):
import json
import os
from klein import Klein
from scrapy import signals
from scrapy.crawler import CrawlerRunner
from twisted.web.server import Site
Site.displayTracebacks = False
class TwistedRunner(CrawlerRunner):
def crawl(self, Spider, *args, **kwargs):
self.items = []
# create spider instance
crawler = self.create_crawler(Spider)
crawler.signals.connect(self.storeItem, signals.item_scraped)
# create deferred crawler-object and register callback
deferred = self._crawl(crawler, *args, **kwargs)
deferred.addCallback(self.getItems)
return deferred
def storeItem(self, item):
self.items.append(item)
def getItems(self, item):
return self.items
def getSpiderResult(output):
"""Format spider result"""
return json.dumps([dict(item) for item in output])
class Router(object):
app = Klein()
scrapeArgument = os.getenv('argument', 'product').encode()
@app.route('/<path:catchall>', methods=['POST', 'GET'])
def catchAll(self, request, catchall):
"""catch-all route"""
request.redirect('/')
@app.route('/', methods=['GET', 'POST'])
def scrape(self, request):
"""Serve request for scrape"""
if self.scrapeArgument not in request.args:
return None
Runner = TwistedRunner()
product=request.args.get(self.scrapeArgument).pop()
a = Runner.crawl(MySpiderCls, product=product)
a.addCallback(getSpiderResult)
return a
if __name__ == '__main__':
Router = Router()
Router.app.run(os.getenv('address', '0.0.0.0'), os.getenv('port', 8080))这工作得很好,正如预期的那样。现在,我想从这一点运行多个爬行器。文档对此非常清楚:
https://docs.scrapy.org/en/latest/topics/practices.html
但是,当我做类似这样的事情时
runner = CrawlerRunner()
runner.crawl(MySpider1)
runner.crawl(MySpider2)
d = runner.join()我看到所有的爬行器都在运行,但是第一个爬行器一完成,HTTP请求就结束了。在这一点上,可能有蜘蛛还没有完成,因此我遗漏了一些项目。要说明此行为,请参阅一些示例日志:
2021-07-29 21:14:27+0200 [-] save item
2021-07-29 21:14:27+0200 [-] (TCP Port 6024 Closed)
2021-07-29 21:14:27+0200 [-] "127.0.0.1" - - [29/Jul/2021:19:14:27 +0000] "GET /?product=anything HTTP/1.1" 200 3 "-" "curl/7.78.0"
2021-07-29 21:14:27+0200 [-] save item正如您所看到的,最终保存的项将永远不会回显给用户,因为请求就在上面完成。
有人知道如何在这个设置中运行多个爬虫吗?另外,如果有什么事情我没有按照scrapy原则来做,请告诉我。
谢谢!
发布于 2021-07-31 19:27:26
您正在使用CrawlerRunner的一个子类,并且重载了crawl()方法,这样它就不会跟踪活动的爬行。您必须添加self._crawl(...),但我不建议这样做,因为您将调用Scrapy作者打算私有的函数。
就像学习练习一样,如果不更改TwistedRunner,代码将如下所示
@app.route('/', methods=['GET', 'POST'])
def scrape(self, request):
ds= set()
Runner = TwistedRunner()
ds.add(Runner.crawl(MySpider1))
ds.add(Runner.crawl(MySpider2))
ds.add(Runner.crawl(MySpider3))
return defer.gatherResults(ds)由于您的Runner.crawl()返回一个DELAY值,因此此示例将它们添加到一个集合中,然后使用defer.gatherResults()等待该集合。
最后,这是你应该做的。不要将自己的CrawlerRunner子类化,只按原样使用类。遵循Scrapy文档上的示例,您将能够使用多个爬行器进行抓取。
https://stackoverflow.com/questions/68593882
复制相似问题