#python #scrapy
#python #scrapy
Вопрос:
В Scrapy 2.4.x на Python 3.8.x я передаю элемент с целью сохранения некоторой статистики в БД. У скребка есть еще один элемент, который также получает результат.
Хотя имя элемента присутствует в основном скрипте «StatsItem», оно теряется в другом классе. Я использую имя элемента, чтобы решить, какой метод вызывать:
в scraper.py:
import scrapy
from crawler.items import StatsItem, OtherItem
class demo(scrapy.Spider):
def parse_item(self, response):
stats = StatsItem()
stats['results'] = 10
yield stats
print(type(stats).__name__)
# Output: StatsItem
print(stats)
# Output: {'results': 10}
в pipeline.py
import scrapy
from crawler.items import StatsItem, OtherItem
class mysql_pipeline(object):
def process_item(self, item, spider):
print(type(item).__name__)
# Output: NoneType
if isinstance(item, StatsItem):
self.save_stats(item, spider)
elif isinstance(item, OtherItem):
# call other method
return item
Выводом print в первом классе является «StatsItem», в то время как в конвейере он является «NoneType», поэтому метод save_stats() никогда не вызывается.
Я довольно новичок в Python, поэтому может быть лучший способ сделать это. Я не знаю ни сообщения об ошибке, ни исключения. Любая помощь приветствуется.
Комментарии:
1. Единственный объект, который имеет тип
NoneType
None
. Таким образом, теряется не только имя — у вас вообще нет значения.2. Вам не нужно наследовать от
(object)
(это неявно, вы можете оставить его выключенным). И если вы получаетеNoneType
в качестве имени типа, это означает, что ваша функция вызывается сitem
помощью beingNone
. Поскольку вы не включаете вызов, невозможно сказать, почему это так, или это даже удивительно.3. Это очень странно. У меня есть аналогичный сканер, в котором работает код копирования / вставки. Я не вижу никакой разницы. Также элемент пуст, когда я распечатываю его внутри элемента процесса, однако он не пуст в методе «demo». Я получаю распечатку словаря и имени класса.
4. это действительно работает? он должен выдать вам сообщение об ошибке, потому
yield
что не может быть введен напрямуюclass
. Это должно быть в каком-то методе — т.е. в методеparse
. in. С текущим кодом мы не можем воспроизвести проблему. Вы можете создать минимальный рабочий код с вашей проблемой, который мы могли бы просто скопировать, запустить и увидеть проблему.5. всегда помещайте полное сообщение об ошибке (начинающееся со слова «Taceback») в вопрос (не комментарий) в виде текста (не скриншота). Есть и другая полезная информация.
Ответ №1:
Вы не можете использовать yield
вне функции imo.
Ответ №2:
Я, наконец, смог найти проблему. Конкретный искатель был почти идентичен всем другим, у которых не было этой проблемы, но, за одним исключением, я настраивал конвейер элементов:
custom_settings.update({
'ITEM_PIPELINES' : {
'crawler.pipelines.mysql_pipeline': 301,
}
})
Удалив это, исправлена проблема.
Комментарии:
1. если вы удалите его, он должен запустить поисковый робот без запуска
mysql_pipeline
2. В том-то и дело, что конвейер был импортирован дважды. Оказавшись внутри settings.py и один раз через обновление настроек непосредственно в искателе. Это вызвало такое неожиданное поведение.
3. то же
pipeline
самое в двух местах — это необычная ситуация, которая может затруднить поиск решения 🙂