Scrapy:将参数从命令行动态传递到管道

时间:2017-12-26 17:12:10

标签: python scrapy

我正在使用scrapy。我有一只以:

开头的蜘蛛
class For_Spider(Spider):

    name = "for"
    table = 'hello' # creating dummy attribute. will be overwritten

    def start_requests(self):

        self.table = self.dc # dc is passed in

我有以下管道:

class DynamicSQLlitePipeline(object):

    @classmethod
    def from_crawler(cls, crawler):
        # Here, you get whatever value was passed through the "table" parameter
        table = getattr(crawler.spider, "table")
        return cls(table)

    def __init__(self,table):
        try:
            db_path = "sqlite:///"+settings.SETTINGS_PATH+"\\data.db"
            db = dataset.connect(db_path)
            table_name = table[0:3]  # FIRST 3 LETTERS
            self.my_table = db[table_name]

当我用:

启动蜘蛛
scrapy crawl for -a dc=input_string -a records=1

在逐步执行执行并在What is the relationship between the crawler object with spider and pipeline objects?之类的问题的帮助下,执行顺序似乎是:

1) For_spider
2) DynamicSQLlitePipeline
3) start_requests

spider“table”中的参数通过from_crawler方法传递给DynamicSQLlitePipeline对象,该方法可以访问scrapy系统的不同组件。表是我设置的初始化为“hello”(虚拟变量)。在执行上面的1和2之后,返回到spider和starts_requests 开始。命令行参数仅在start_requests中可用,因此在管道已经实例化时动态设置表名为时已晚。

因此我不知道是否有办法动态设置管道表名称。我怎么能这样做。

编辑:

elRuLL是正确的,他的解决方案有效。我在步骤1中查看了蜘蛛对象,但未发现蜘蛛中列出的任何参数。我错过了吗?

>>> Spider.__dict__
mappingproxy({'__module__': 'scrapy.spiders', '__doc__': 'Base class for scrapy spiders. All spiders must inherit from this\n    class.\n    ', 'name': None, 'custom_settings': None, '__init__': <function Spider.__init__ at 0x00000000047A6D90>, 'logger': <property object at 0x0000000003E0E598>, 'log': <function Spider.log at 0x00000000047A6EA0>, 'from_crawler': <classmethod object at 0x0000000003B28278>, 'set_crawler': <function Spider.set_crawler at 0x00000000047C9048>, '_set_crawler': <function Spider._set_crawler at 0x00000000047C90D0>, 'start_requests': <function Spider.start_requests at 0x00000000047C9158>, 'make_requests_from_url': <function Spider.make_requests_from_url at 0x00000000047C91E0>, 'parse': <function Spider.parse at 0x00000000047C9268>, 'update_settings': <classmethod object at 0x0000000003912C88>, 'handles_request': <classmethod object at 0x0000000003E0B7F0>, 'close': <staticmethod object at 0x0000000004756BA8>, '__str__': <function Spider.__str__ at 0x00000000047C9488>, '__repr__': <function Spider.__str__ at 0x00000000047C9488>, '__dict__': <attribute '__dict__' of 'Spider' objects>, '__weakref__': <attribute '__weakref__' of 'Spider' objects>})

2 个答案:

答案 0 :(得分:2)

在文档中有示例how to create pipeline to write in MongoDB

使用def open_spider(self, spider):打开数据库 并且有变量spider,可让您访问蜘蛛,以便获取变量

def open_spider(self, spider):

    table = spider.table

所以它可能(类似于文档中的代码)

class DynamicSQLlitePipeline(object):

    def open_spider(self, spider):

        table = spider.table

        try:
            db_path = "sqlite:///"+settings.SETTINGS_PATH+"\\data.db"
            self.db = dataset.connect(db_path)
            table_name = table[0:3]  # FIRST 3 LETTERS
            self.my_table = self.db[table_name]
         # ... rest ...

    def close_spider(self, spider):
        self.db.close()

    def process_item(self, item, spider):
        self.my_table.insert_one(dict(item))
        return item

答案 1 :(得分:1)

Scrapy参数动态传递给spider实例,稍后可以在Spider中使用self变量。

现在,start_requests 不是第一个可以检查蜘蛛参数的地方,当然那将是Spider实例的构造函数(但要小心,因为{{ 1}}也将重要的参数传递给它的构造函数。)

现在您的问题是您尝试访问Pipeline构造函数上的类变量scrapy(因为table在构造函数之前执行),这是不正确的,因为您正在分配{{ 1}} from_crawler尚未发生的事情。

正确的方法是直接获取self.table,因为蜘蛛从命令行获取了start_requests变量。