如何以正确的顺序导入Scrapy项目密钥?

时间:2018-10-09 06:25:33

标签: python python-3.x scrapy scrapy-pipeline

我正在将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()时,将保留顺序!但是我需要访问,以便在 之前被删除。

2 个答案:

答案 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']