【问题标题】:Instantiate multiple spiders from a single class in Scrapy在 Scrapy 中从单个类实例化多个蜘蛛
【发布时间】:2018-04-01 17:42:10
【问题描述】:

为了在一个非常大的项目中节省时间和重复代码行,我一直在尝试在 Scrapy 中从单个类定义中实例化多个蜘蛛。我在文档中没有发现这是一种标准做法,但我也没有发现任何迹象表明它不能或不应该这样做。但是,它不起作用。这是我正在尝试的:

from scrapy.spider import CrawlSpider

class ExampleSpider(CrawlSpider):

    def __init__(self, name, source, allowed_domains, starturls):
        self.name = name
        self.custom_settings = {'LOG_FILE':'logs/' + name + '.txt' }
        self.source = source
        self.allowed_domains = allowed_domains   
        self.start_urls = starturls
        self.rules = ( Rule(LinkExtractor(allow=''), callback='parse_item', follow=True),) 

     def parse_item(self, response):
        # do stuff here

SpiderInstance = ExampleSpider (
  'columbus',
  'Columbus Symphony',
  'columbussymphony.com',
 [ 'http://www.columbussymphony.com/events/'],  
) 

我得到的错误是:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/bin/scrapy", line 11, in <module>
sys.exit(execute())
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scrapy/cmdline.py", line 150, in execute
_run_print_help(parser, _run_command, cmd, args, opts)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scrapy/cmdline.py", line 90, in _run_print_help
func(*a, **kw)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scrapy/cmdline.py", line 157, in _run_command
cmd.run(args, opts)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scrapy/commands/crawl.py", line 57, in run
self.crawler_process.crawl(spname, **opts.spargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scrapy/crawler.py", line 170, in crawl
crawler = self.create_crawler(crawler_or_spidercls)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scrapy/crawler.py", line 198, in create_crawler
return self._create_crawler(crawler_or_spidercls)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scrapy/crawler.py", line 202, in _create_crawler
spidercls = self.spider_loader.load(spidercls)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scrapy/spiderloader.py", line 71, in load
raise KeyError("Spider not found: {}".format(spider_name))
KeyError: 'Spider not found: columbus'

是否可以以这种方式使用 Scrapy,如果可以,我做错了什么?

【问题讨论】:

  • 你是不是在scrapy import Spider的顶部添加了这段代码
  • 啊,好点——但是我做到了。为了清楚起见,我会将其添加到问题中。
  • 也许你应该尝试这种方式。从 scrapy.spider 导入 CrawlSpider
  • 您没有收到比这更长的错误消息吗?发布整个堆栈跟踪,以便我们可以轻松发现哪一行出错。
  • 你需要super().__init__() CrawlSpider 类。

标签: python scrapy scrapy-spider


【解决方案1】:

1.

scrapy 寻找蜘蛛 classes,而不是 instances

在您的代码中,ExampleSpider 是一个,而SpiderInstance 是它的一个实例

您可能需要这样做:

class ColumbusSpider(ExampleSpider):
    name = 'columbus'
    source = 'Columbus Symphony'
    allowed_domains = ['columbussymphony.com']
    start_urls = ['http://www.columbussymphony.com/events/']

2.

还值得注意的是,蜘蛛的allowed_domains 属性应该包含一个列表、元组或一组域。在您的示例代码中,它是一个字符串。

3.

您也可以将ExampleSpider 设为元类,而不是像#1 中所示将ExampleSpider 子类化。因此,实例化 ExampleSpider 将为您带来一个类,而不是类实例。

【讨论】:

  • #1 导致我试图避免的情况:为每个蜘蛛重复“name = ...”、“source = ...”等等。必须有一种方法将这些值作为参数传递,而不是为每个蜘蛛手动写出它们。同样,如果我的蜘蛛方法(parse_item 等)可以接收参数来自定义每个蜘蛛的行为,它们是可重用的。否则我只是复制和粘贴类定义并更改它们的细节,数百次。选项 3 听起来像我正在寻找的。能否详细说明如何应用?
【解决方案2】:

看完@starrify的回答,一个我之前没去过的简单解决方案:

def class_factory(passed_name, passed_source, passed_allowed_domains, passed_start_urls):

   class ColumbusSpider(ExampleSpider):
       name = passed_name
       source = passed_source
       allowed_domains = passed_allowed_domains   
       start_urls = passed_start_urls
       # ... other stuff
       def parse_item(self, response):
           # use any other passed parameters as needed

   return ColumbusSpider

columbus = class_factory ( 
'columbustest',
'Columbus Symphony',
['columbussymphony.com'], 
[ 'http://www.columbussymphony.com/events/'],    
) # use as many times as needed

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 2016-02-14
    • 1970-01-01
    相关资源
    最近更新 更多