【问题标题】:How to import Scrapy item keys in the correct order?如何以正确的顺序导入 Scrapy 项目密钥?
【发布时间】:2019-03-13 20:26:26
【问题描述】:

我正在将 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() 时,将保留顺序!但我需要访问 keys 以便 before item 被刮掉。

【问题讨论】:

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


    【解决方案1】:

    一个简单的解决方法是在 Item 类中定义 keys() 方法:

    class MyItem(Item):
        foo = Field()
        bar = Field()
        gar = Field()
        cha = Field()
    
        def keys(self):
            # in your preferred order
            return ['cha', 'gar','bar','foo']
    

    【讨论】:

    • 这不起作用。我仍然得到字母顺序AdId,AdURL,DateR。你在使用 Python2 吗? (我使用的是 Python3)。
    • 嗯我很久以前才用过这个,也许新版本的scrapy不再支持键覆盖了,去测试一下。
    • 您可以通过导入 items.py 从 scrapy shell 测试它。完全没有效果。至少对我来说。
    【解决方案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 以意想不到的方式对 dict 进行排序的奇怪方式。

    【讨论】:

      猜你喜欢
      • 2019-11-10
      • 1970-01-01
      • 2015-09-10
      • 1970-01-01
      • 1970-01-01
      • 2014-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多