如何以正确的顺序导入 Scrapy item keys?
How to import Scrapy item keys in the correct order?
我正在将 Scrapy 项目密钥从 items.py
导入 pipelines.py
。
问题是导入项目的 order 与它们在 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
。
如何保证导入的顺序不变?
注意: 这可能与 有关,但完全不清楚发生了什么,因为 Python3 文档指出列出和听写应该保留他们的顺序。另请注意,当使用 process_item()
和使用 item.keys()
时,顺序将保留!但是我需要访问 keys 以便 before item 被抓取。
一个简单的解决方法是在 Item
class:
中定义 keys()
方法
class MyItem(Item):
foo = Field()
bar = Field()
gar = Field()
cha = Field()
def keys(self):
# in your preferred order
return ['cha', 'gar','bar','foo']
我能让它工作的唯一方法是按以下方式使用 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 以意想不到的方式对字典进行排序的奇怪方式。
我正在将 Scrapy 项目密钥从 items.py
导入 pipelines.py
。
问题是导入项目的 order 与它们在 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
。
如何保证导入的顺序不变?
注意: 这可能与 process_item()
和使用 item.keys()
时,顺序将保留!但是我需要访问 keys 以便 before item 被抓取。
一个简单的解决方法是在 Item
class:
keys()
方法
class MyItem(Item):
foo = Field()
bar = Field()
gar = Field()
cha = Field()
def keys(self):
# in your preferred order
return ['cha', 'gar','bar','foo']
我能让它工作的唯一方法是按以下方式使用 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 以意想不到的方式对字典进行排序的奇怪方式。