2017-07-17 65 views
2

我有一个蜘蛛,它从一个redis列表中获取URL。Scrapy关闭蜘蛛如果没有网址爬行

我想在没有找到URL时很好地关闭spider。我试图执行CloseSpider例外,但它似乎并没有达到这个地步

def start_requests(self): 
    while True: 
     item = json.loads(self.__pop_queue()) 
     if not item: 
      raise CloseSpider("Closing spider because no more urls to crawl") 
     try: 
      yield scrapy.http.Request(item['product_url'], meta={'item': item}) 
     except ValueError: 
      continue 

即使我提高CloseSpider例外,但我仍然得到下面的错误:

[email protected]:/scrapper# scrapy crawl general -a country=my -a log=file 
2017-07-17 12:05:13 [scrapy.core.engine] ERROR: Error while obtaining start requests 
Traceback (most recent call last): 
    File "/usr/local/lib/python2.7/site-packages/scrapy/core/engine.py", line 127, in _next_request 
    request = next(slot.start_requests) 
    File "/scrapper/scrapper/spiders/GeneralSpider.py", line 20, in start_requests 
    item = json.loads(self.__pop_queue()) 
    File "/usr/local/lib/python2.7/json/__init__.py", line 339, in loads 
    return _default_decoder.decode(s) 
    File "/usr/local/lib/python2.7/json/decoder.py", line 364, in decode 
    obj, end = self.raw_decode(s, idx=_w(s, 0).end()) 
TypeError: expected string or buffer 

而且,我也尝试在相同的函数中捕获TypeError,但它也不起作用。

是否有处理这种

感谢任何推荐的方式

回答

4

您需要检查是否self.__pop_queue()回报你给json.loads()(或捕捉TypeError调用它时),像之前的东西:

def start_requests(self): 
    while True: 
     item = self.__pop_queue() 
     if not item: 
      raise CloseSpider("Closing spider because no more urls to crawl") 
     try: 
      item = json.loads(item) 
      yield scrapy.http.Request(item['product_url'], meta={'item': item}) 
     except (ValueError, TypeError): # just in case the 'item' is not a string or buffer 
      continue 
+0

很好的方式做到这一点,得益于 –

+0

@BLANQUERAdrien - 超越你自己的问题,并发布您的代码/错误,我们会看到发生了什么,这是更适合OP的问题,优雅地退出其发电机功能。 – zwer

+0

@zwer感谢它现在按预期工作。有一件事我仍然困惑。在什么时候我们可以捕捉到蜘蛛的例外。我的意思是scrapy框架是什么标准?谢谢 –

1

我有同样的问题,发现一个小窍门。当蜘蛛在空闲(当它什么都不做)时,我检查在redis队列中是否还有剩下的东西。如果没有,我用close_spider关闭蜘蛛。下面的代码位于spider类:

@classmethod 
def from_crawler(cls, crawler, *args, **kwargs): 
    from_crawler = super(SerpSpider, cls).from_crawler 
    spider = from_crawler(crawler, *args, **kwargs) 
    crawler.signals.connect(spider.idle, signal=scrapy.signals.spider_idle) 
    return spider 


def idle(self): 
    if self.q.llen(self.redis_key) <= 0: 
     self.crawler.engine.close_spider(self, reason='finished') 
+0

这是一个信息丰富的兄弟。尚未使用信号。谢谢 –