Python Scrapy — как вызвать переменную из другого метода spider?

#scrapy #python-3.7

#шершавый #python-3.7 #scrapy

Вопрос:

Итак, я пытаюсь изучить scrapy, и для учебного проекта я хочу очистить названия элементов этого сайта (всего из 1 категории atm)https://www.killertools.com/Dent-Removal-Aluminum-Steel_c_11.html а затем введите URL-адреса этих элементов и возьмите текст описания.

У меня уже есть предложение написать 2 паука, но я не знаю, как извлечь данные из переменной в методе parse из первого паука во второй паук, чтобы заполнить start_urls.

Вот где я нахожусь:

 import scrapy


class Names(scrapy.Spider):

    name = 'killernames'

    start_urls = ['https://www.killertools.com/Dent-Removal-Aluminum-Steel_c_11.html?viewall=1',]

    def parse(self, response):
        self.detail = response.xpath('//div[contains(@class, "product-item")]/div[@class="name"]/a/@href').getall()

        for item in response.xpath('//div[@class="name"]'):
            yield {
                'name': item.xpath('./a/text()').extract_first(),
                'url': item.xpath('./a/@href').extract_first(),
                 }

class Detail(scrapy.Spider):

    name = 'killerdetail'

    start_urls = []

    for item in self.detail: (I dont know how to get it from first spider)
        url = 'https://www.killertools.com/'   item
        start_urls.append(url)



    def parse(self, response):

        for item in response.xpath('//div[@itemprop="description"]'):
            yield {
                   'detail': item.xpath('./p/strong/text()').extract_first(),
                  }
  

Ответ №1:

Вместо использования двух пауков вы можете переходить по ссылкам на отдельные страницы, используя одного паука. Сначала несколько пунктов по созданию spider, за которыми следуют некоторые концепции, которые вам нужно понять, чтобы выполнить этот тип очистки. Затем пример кода и объяснение ниже.

Обзор кода

  • Используйте get() вместо extract_first() , это более лаконично, всегда даст вам строку, и документы scrapy предлагают это
  • Не путайте использование getall() с extract() . Иногда extract() выдает вам список или строку, getall() всегда будет выдавать вам список.
  • Используйте словарь элементов, а не выдавать словарь. Особенно в этом случае, когда данные не являются чистыми.

Понятия, которые нужно знать

Товары

Словарь элементов — это нестандартный способ сбора данных scrapy. Это позволяет вам изменять данные, поступающие и выводимые позже, если это необходимо. Это более гибко, чем предоставление словаря. Для начала использования элементов вам необходимо включить имена полей в items.py которые вы хотите использовать в качестве потенциальных столбцов. В данном случае имя, URL, описание.

items.py

импортировать scrapy

 class KillerItem(scrapy.Item):
   
    name = scrapy.Field()
    url = scrapy.Field()
    description = scrapy.Field()
  

Мы создаем класс KillerItem, который относится к подклассу scrapy.Item. Мы создаем экземпляр объекта Field() и называем его именами, которые мы хотим получить в виде столбцов.

Вам также необходимо включить в свой скрипт spider

 from ..items import KillerItem
  

Это относительный импорт, .. означает родительский каталог, где items.py живет.
KillerItem — это класс, который необходимо создать для создания словаря элементов. Мы делаем это с помощью приведенного ниже кода.

 items = KillerItem()
  

Который создает словарь элементов, но у него есть ключи, соответствующие нашим именам полей, которые мы создали в items.py . Итак, теперь мы можем заполнить эти ключи значениями, которые соответствуют нужным нам данным. В этом случае имя, URL и описание.

 items['name] = ...
  

Когда мы закончим заполнять словарь элементов, который мы должны использовать yield items . Это важно, поскольку мы хотим получить результат, когда у нас есть имя, URL и описание для каждой отдельной страницы.

Использование мета-аргумента

Вы можете передавать переменные из функции в функцию с помощью мета-аргумента запроса scrapy. Аргумент meta принимает словарь, в данном случае мы хотим передать словарь элементов, который мы создаем в функции parse, с именем и URL-адресами. Мы хотим заполнить этот словарь элементов описаниями с отдельных страниц. Мы делаем это, создавая словарь с ключом по нашему выбору, а затем значением является наш словарь элементов, который мы определили при создании экземпляра класса KillerItems.

 meta= {'items',items}
  

Чтобы получить доступ к этому словарю элементов в следующей функции, т. Е. Там, где происходит синтаксический анализ отдельных страниц. Мы можем получить доступ через ответ

 items = response.meta['items']
  

Мы придерживаемся нашей переменной items и получаем доступ к значению через meta[‘items’]

Теперь, когда это объяснено, мы можем перейти к примеру кода.

Пример кода

 import scrapy
from ..items import KillerItem

class Names(scrapy.Spider):

    name = 'killernames'

    start_urls = ['https://www.killertools.com/Dent-Removal-Aluminum-Steel_c_11.html?viewall=1']

    def parse(self, response):
        

        for item in response.xpath('//div[@class="name"]'):
            items = KillerItem()
          
            items['name'] = item.xpath('./a/text()').get()
            items['url'] = 'https://www.killertools.com/'   item.xpath('./a/@href').get()
            

            
            yield response.follow(url=items['url'], callback=self.page, meta={'items':items})
           
    def page(self,response):
       
        items = response.meta['items']
        base = response.xpath('//div[@itemprop="description"]')
        if base.xpath('./p/strong/text()') and base.xpath('./p/span/text()'):
            items['description'] = base.xpath('./p/strong/text()').get().replace('xa0','')   base.xpath('./p/span/text()').get().replace('xa0','')
        elif base.xpath('./p/strong/text()'):
            items['description'] = base.xpath('./p/strong/text()').get().replace('xa0','')
        elif base.xpath('./p/span/text()'):
            items['description'] = base.xpath('./p/span/text()').get().replace('xa0','')
        elif base.xpath('./span/text()'):
            items['description'] = base.xpath('./span/text()').get().replace('xa0','')
        elif base.xpath('./h3/text()'):
            items['description'] = base.xpath('./h3/text()').get().replace('xa0','')
        else:
            items['description'] = base.xpath('./text()').get()
        yield items
  

Объяснение

В функции синтаксического анализа мало что изменилось, мы создаем значения, используя ваши селекторы xpath для name и URL. Мы заполняем ключ items, соответствующий именам полей, которые мы создали в items.py .

. Мы используем ответ.следуя методу, в аргументах мы указываем URL-адрес items[‘url’] для каждой итерации цикла for и функции обратного вызова, которую мы вызываем self.page , у нас также есть аргумент meta, который создает простой словарь имен элементов и значение нашего словаря items, созданного для передачи нашего словаря items в функцию parse.

В функции pages у нас тогда есть довольно много операторов elif, потому что описание каждой страницы, к сожалению, не соответствует.

Наконец, мы получаем словарь элементов, теперь у нас есть описание для каждой отдельной страницы.

На самом деле вы не указали маркерные пункты описания, но у вас должно быть достаточно, чтобы пойти и получить эту дополнительную дату, если вам это нужно.

Комментарии:

1. Вы, сэр, БОГ среди людей! К сожалению, у меня пока нет представителя, чтобы проголосовать за это, но вы в основном сэкономили мне, вероятно, больше недели на чтении документации, которую я с трудом понимаю, так что, вероятно, даже еще 1 неделя слепого тестирования, что что делает. 4 месяца назад я начал смотреть некоторые вещи для начинающих на Python, такие как print («Привет, мир!») материал уровня. Все еще многие концепции меня чертовски смущают, особенно в фреймворках, где все работает в бэкэнде. Поэтому мне проще всего учиться, разбирая рабочие примеры. Еще раз спасибо!

2. Добро пожаловать! Не могли бы вы отметить мой ответ как принятый в левой части ответа? Спасибо! Python сложный, но продолжайте в нем. Это становится проще.