Как импортировать ключи элемента Scrapy в правильном порядке? - PullRequest
0 голосов
/ 09 октября 2018

Я импортирую ключи элемента 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.

Как я могуубедитесь, что импортированный заказ остается прежним?

Примечание: Это может быть связано с Как получить порядок полей в элементе Scrapy , но это не таксовершенно ясно, что происходит, так как документы Python3 указывают, что списки и слова должны сохранять свой порядок.Также обратите внимание, что при использовании process_item() и item.keys() порядок сохраняется!Но мне нужно получить доступ к ключам , чтобы до того, как item будут очищены.

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Единственный способ заставить это работать - это использовать это решение следующим образом.

Мой 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 сортировки диктов неожиданным образом.

0 голосов
/ 09 октября 2018

Простое исправление - определить метод 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']
...