Scrapy: предотвращение сохранения данных и загрязнения перекрестных запросов в ItemLoaderPython

Программы на Python
Ответить
Anonymous
 Scrapy: предотвращение сохранения данных и загрязнения перекрестных запросов в ItemLoader

Сообщение Anonymous »

Я использую Scrapy для сканирования страниц и извлечения данных в файл JSON, но столкнулся с проблемами согласованности данных. В частности, в некоторых полях сохраняются или дублируются данные из предыдущих ответов, что приводит к неправильным значениям полей в выходных данных.
Проблема
Выходной файл JSON содержит правильное количество элементов, соответствующее количеству URL-адресов в файле .txt, причем все URL-адреса уникальны. Однако некоторые поля в выводе JSON неверны и выглядят так, как будто данные из одного запроса сохраняются в другом элементе.
Я это проверил:
  • Для каждого ответа создается новый экземпляр ItemLoader.
  • Я использовал операторы if-else, чтобы добавить сообщение «НЕТ ДАННЫХ НЕ НАЙДЕНО», если данные не найдены. по указанному XPath.
Вот пример двух последовательных строк с разными URL-адресами, содержащими одинаковые данные:

Строка 20:
  • Объект контрато: Проект Ejecución «Abastecimiento Caseríos [...]»
    < li>База предполагаемой суммы: 247 576,09 евро
  • URL: Ссылка на место заключения контракта
Line 21:
  • Объект контрато: проект Ejecución «Abastecimiento Caseríos [...]»
  • Предполагаемая база: 247 576,09 евро.
  • URL: Ссылка на место контракта по государству
Разумным подходом было бы используйте Spider вместо CrawlSpider. Однако я намерен усложнить код, как только эта первоначальная версия будет решена.
Код

Краткая информация о базовой структуре

  • Импорт и определения:
  • Импортировать ключевые модули Scrapy (элемент, поле , CrawlSpider, Rule, ItemLoader и LinkExtractor).
  • Класс элемента (Claselicitacion):
  • Определяет поля: objeto_contrato, presupuesto_base и url.
  • Класс Spider (LicitacionCrawlSpider):
  • Наследует от CrawlSpider .
  • Считывает URL-адреса из текстового файла (1_DeepLinks.txt) для инициализации start_urls.
  • Определяет правила для извлечения определенных ссылок и назначения их parse_item обратный вызов.
  • Метод обратного вызова (parse_item):
    • Создает новый экземпляр ItemLoader для каждого ответа.
    • Извлекает данные для каждого поля с помощью XPath.
    • Добавляет URL-адрес ответа.
    • Получает загруженный элемент (item.load_item()).
    • Вот основная структура моего кода:

    Код

    Код: Выделить всё

    from scrapy.item import Item, Field
    from scrapy.spiders import CrawlSpider, Rule
    from scrapy.loader import ItemLoader
    from scrapy.linkextractors import LinkExtractor
    
    class Claselicitacion(Item):
    objeto_contrato = Field()
    presupuesto_base = Field()
    url = Field()
    
    class LicitacionCrawlSpider(CrawlSpider):
    name = 'licitacion_crawl'
    custom_settings = {
    "REQUEST_FINGERPRINTER_IMPLEMENTATION": "2.7",
    'USER_AGENT': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36',
    'FEED_EXPORT_ENCODING': 'utf-8',
    'FEEDS': {
    '2_ProjectFinder.json': {
    'format': 'json',
    'encoding': 'utf-8',
    },
    }
    }
    
    with open('1_DeepLinks.txt', 'r') as file:
    start_urls = [line.strip() for line in file if line.strip()]
    
    rules = (
    Rule(
    LinkExtractor(allow=r'deeplink%3Adetalle_licitacion'),
    callback='parse_item',
    follow=False,
    ),
    )
    
    def parse_item(self, response):
    item = ItemLoader(item=Claselicitacion(), response=response)
    
    if response.xpath('//li[@id="fila4_columna2"]'):
    item.add_xpath('objeto_contrato', '//li[@id="fila4_columna2"]//span[@class="outputText"]/text()')
    else:
    item.add_value('objeto_contrato', 'NO DATA FOUND')
    
    if response.xpath('//li[@id="fila5_columna2"]'):
    item.add_xpath('presupuesto_base', '//li[@id="fila5_columna2"]//span[@class="outputText"]/text()')
    else:
    item.add_value('presupuesto_base', 'NO DATA FOUND')
    
    item.add_value('url', response.url)
    
    yield item.load_item()
    
    Вопросы
  • Сохраняет ли ItemLoader значения из предыдущих запросов? Как могу ли я обеспечить полное разделение данных каждого ответа?
  • Правильно ли я использую ItemLoader? Есть ли лучший способ справиться с этой настройкой? li>
    Может ли асинхронная обработка Scrapy вызвать путаницу данных? Как я могу обеспечить независимую обработку каждого запроса?
  • Является ли item.add_xpath + Give item.load_item() надежным подходом? Поскольку поля URL всегда корректны, могут ли возникнуть проблемы с использованием add_xpath?
Что я пробовал
  • Добавление условий if-else для установки " НЕТ ДАННЫХ НАЙДЕНО» в качестве заполнителя, когда данные не найдены.
  • Гарантируется, что экземпляр ItemLoader создается заново для каждого ответа.
  • Подтверждение что URL-адреса в моем исходном файле верны.
Ожидаемое поведение
Каждый элемент выходных данных должен быть независимым и содержать только данные, относящиеся к соответствующему URL-адресу. Если данные поля недоступны, в нем должно быть явно указано «ДАННЫЕ НЕ НАЙДЕНЫ».
Любые идеи или предложения по улучшению использования моего ItemLoader или изоляции состояний запроса в Scrapy будут быть очень полезным. Заранее спасибо!
РЕДАКТИРОВАТЬ
У меня не так уж много кода: файл DeepLinks.txt; файл Python «2_ProjectFinder_SoF.py»; созданный файл json.
Это тип содержимого в файле DeepLinks.txt (каждый URL-адрес в отдельной строке, всего 128 строк):

https://contrataciondelestado.es/wps/po ... Scog%3D%3D

https://contrataciondelestado.es/wps/po ... ion&idEvl= ywAdehRW01iKeVWTb9Scog%3D%3D

https://contrataciondelestado.es/wps/po ... tG9A%3D%3D
Я запускаю файл Python через терминал с помощью: #python -m Scrapy RunSpider 2_ProjectFinder_SoF.py

Это создает файл JSON с именем 2_ProjectFinder.json.
При просмотре файла JSON Я заметил некоторые записи с повторяющимися или смешанными данными. Например:

Строка 23: {"objeto_contrato": ["Реновация питьевой воды из фиброцемента"], "presupuesto_base": ["84,072.74"], "url": ["https: //contrataciondelestado.es/wps/portal/!ut/p/b0/04_Sj9CPykssy0xPLMnMz0vMAfIjU1JTC3Iy87KtUlJLEnNyUuNzMpMzSxKTgQr0w_Wj9KMyU1zLcvQjnT08kyyNVQ0CKrw8Uz2dvII8AjMD sgNtbfULcnMdAS3u5Sw!/"]},
Строка 32: {"objeto_contrato": ["Обновление воды питьевой фиброцемент"], "presupuesto_base": ["84,072.74"], "url": ["https://contrataciondelestado.es/wps/po ... MpMzSxKTgQ r0w_Wj9KMyU1zLcvQj_VK9nFzTigJUDar8wrJDEpNCVA2CfC0cbW31C3JzHQFWfu8j/"]},
В этом примере строки 23 и 32 содержат разные URL-адреса, но идентичные данные. Строка 32 выглядит корректной, а строка 23, возможно, случайно извлекла информацию из строки 32.
Я дважды проверил, и в файле JSON содержится 101 запись вместо ожидаемых 128. , что указывает на потенциальную проблему с чтением файла DeepLinks.txt. Но я не понимаю, как

Подробнее здесь: https://stackoverflow.com/questions/791 ... -itemloade
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»