自定义BaseSpider Scrapy

Rah*_*eel 0 python scrapy scrapy-spider

我想在自定义基本蜘蛛类中具有一些针对蜘蛛的通用功能。

通常,y抓的蜘蛛从scrapy.Spider类继承。

我尝试在scrapy的spiders文件夹中创建BaseSpider类,但该类无效

import scrapy


class BaseSpider(scrapy.Spider):
    def __init__(self):
        super(scrapy.Spider).__init__()

    def parse(self, response):
        pass
Run Code Online (Sandbox Code Playgroud)

这是我真正的蜘蛛

import scrapy
import BaseSpider


class EbaySpider(BaseSpider):
    name = "ebay"
    allowed_domains = ["ebay.com"]

    def __init__(self):
        self.redis = Redis(host='redis', port=6379)
    # rest of the spider code
Run Code Online (Sandbox Code Playgroud)

给出这个错误

TypeError: Error when calling the metaclass bases
    module.__init__() takes at most 2 arguments (3 given)
Run Code Online (Sandbox Code Playgroud)

然后我尝试使用多重继承,使我的eBay Spider看起来像

class EbaySpider(scrapy.Spider, BaseSpider):

    name = "ebay"
    allowed_domains = ["ebay.com"]

    def __init__(self):
        self.redis = Redis(host='redis', port=6379)
    # rest of the spider code 
Run Code Online (Sandbox Code Playgroud)

这使

TypeError: Error when calling the metaclass bases

metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
Run Code Online (Sandbox Code Playgroud)

我是python的新手,也是scrapy的新手,我想在其中实现我的PHP编码风格,但我想这行不通。

我正在寻找合适的方法。

谢谢

更新

根据scrapy.Spider 更改了初始化签名

BaseSpider

def __init__(self, *args, **kwargs):
        super(scrapy.Spider, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

易趣蜘蛛

class EbaySpider(BaseSpider):
    def __init__(self, *args, **kwargs):
        super(BaseSpider,self).__init__(*args, **kwargs)
        self.redis = Redis(host='redis', port=6379)
Run Code Online (Sandbox Code Playgroud)

仍在

File "/scrapper/scrapper/spiders/ebay.py", line 11, in <module>
    class EbaySpider(BaseSpider):
TypeError: Error when calling the metaclass bases
    module.__init__() takes at most 2 arguments (3 given)
Run Code Online (Sandbox Code Playgroud)

Mik*_*bov 5

看一下scrapy.Spider.__init__ 签名

def __init__(self, name=None, **kwargs):
    # ...
Run Code Online (Sandbox Code Playgroud)

子类应定义__init__具有相同签名的方法。如果您不关心名称和名称,只需将它们传递给基类:

class BaseSpider(scrapy.Spider):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def parse(self, response):
        pass
Run Code Online (Sandbox Code Playgroud)

如果EbaySpider已经从BaseSpider继承,则不必从scrapy.Spider继承。它也应该具有相同的__init__签名,并且还需要调用super()

class EbaySpider(BaseSpider):

    name = "ebay"
    allowed_domains = ["ebay.com"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.redis = Redis(host='redis', port=6379)
Run Code Online (Sandbox Code Playgroud)

(我使用的是Python 3语法super()

编辑

还有一个问题:您要像这样导入BaseSpider:

import BaseSpider
Run Code Online (Sandbox Code Playgroud)

可能您有一个名为BaseSpider的模块(BaseSpider.py文件),并且在该模块内部有一个名为BaseSpider的类。import BaseSpider给您模块对象,而不是蜘蛛类。尝试使用from BaseSpider import BaseSpider,最好将其重命名以避免混淆并遵循pep-8