我正在使用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>})
答案 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
变量。