我正在将Scrapy项目密钥从items.py
导入到pipelines.py
中。
问题在于,导入项目的顺序与items.py
文件中的定义方式不同。
我的items.py
文件:
class NewAdsItem(Item):
AdId = Field()
DateR = Field()
AdURL = Field()
在我的pipelines.py
中:
from adbot.items import NewAdsItem
...
def open_spider(self, spider):
self.ikeys = NewAdsItem.fields.keys()
print("Keys in pipelines: \t%s" % ",".join(self.ikeys) )
#self.createDbTable(ikeys)
输出为:
Keys in pipelines: AdId,AdURL,DateR
而不是预期的:AdId,DateR,AdURL
。
如何确保导入的订单保持不变?
注意::这可能与How to get order of fields in Scrapy item有关,但是由于Python3文档指出列表和字典应保留其顺序,因此目前还不清楚。另请注意,当使用process_item()
和item.keys()
时,将保留顺序!但是我需要访问键,以便在 之前被删除。
答案 0 :(得分:2)
我要使其正常工作的唯一方法是按以下方式使用this solution。
我的 items.py
文件:
from scrapy.item import Item, Field
from collections import OrderedDict
from types import FunctionType
class StaticOrderHelper(type):
# Requires Python3
def __prepare__(name, bases, **kwargs):
return OrderedDict()
def __new__(mcls, name, bases, namespace, **kwargs):
namespace['_field_order'] = [
k
for k, v in namespace.items()
if not k.startswith('__') and not k.endswith('__')
and not isinstance(v, (FunctionType, classmethod, staticmethod))
]
return type.__new__(mcls, name, bases, namespace, **kwargs)
class NewAdsItem(metaclass=StaticOrderHelper):
AdId = Field()
DateR = Field()
AdURL = Field()
然后通过以下方式将_field_order
项目导入到您的 piplines.py
中:
...
from adbot.items import NewAdsItem
...
class DbPipeline(object):
ikeys = NewAdsItem._field_order
...
def createDbTable(self):
print("Creating new table: %s" % self.dbtable )
print("Keys in creatDbTable: \t%s" % ",".join(self.ikeys) )
...
现在,我可以按照正确的外观顺序创建新的数据库表,而不必担心Python以奇怪的方式对字典进行排序的怪异方式。
答案 1 :(得分:0)
一个简单的解决方法是在keys()
类中定义Item
方法:
class MyItem(Item):
foo = Field()
bar = Field()
gar = Field()
cha = Field()
def keys(self):
# in your preferred order
return ['cha', 'gar','bar','foo']