Scrapy - извлечение данных из нескольких страниц - PullRequest
5 голосов
/ 14 февраля 2020
class HomedepotcrawlSpider(scrapy.Spider):
      name = 'homeDepotCrawl'
      allowed_domains = ['homedepot.com']
      start_urls = ['https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=0']

def parse(self, response):

    #call home depot function
    for item in self.parseHomeDepot(response):
        yield item

    nextPageSelect = '.hd-pagination__link'
    next_page = response.css(nextPageSelect).getall()
    if next_page:
        yield scrapy.Request(
            response.urljoin(next_page),
            callback=self.parse
        )

Редактировать-

Я получил .hd-pagination__link используя расширение селектора CSS для Google chrome и выбрал значок следующей страницы (Снимок экрана прилагается)

Screenshot of css for next page

Итак, я попробовал несколько вещей, и именно этот способ имел для меня наибольшее значение, и я думаю, что я просто беру не тот объект для Следующая страница. На данный момент моя программа только получает данные с первой страницы и кажется, что блок кода для обхода страниц игнорируется.

Я нашел шаблон с URL-адресом, где номера страниц обозначаются с шагом 24 (может быть из-за номеров элементов?). Пример:

Страница 1: https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=0

Страница 2: https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=24

Стр. 3: https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=48. , , , , , .

стр. N: https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao= [(n * 24) - 24]

и т. Д.

Когда я пытался протестировать код, связанный с номера страниц [увеличивая число после Na0 = x], я бы просто l oop через первую страницу x количество раз. (Мой вывод будет первой страницей (24 элемента), повторенной x раз.

Я также изучил паук сканирования, но не смог понять его / реализацию.

Любая помощь с моим кодом / разъяснениями по другим методам будет приветствоваться!

Также это не вся моя программа, я не использую свою функцию parseHomeDepot, потому что я не думаю, что это необходимо, но если код нужен , просто дай мне знать!

Ответы [ 3 ]

4 голосов
/ 14 февраля 2020

Мне кажется, у вас есть пара проблем.

Прежде всего, вы можете получить весь элемент html, содержащий ссылку для следующей страницы, тогда как вы ищете только ссылка. Поэтому я предлагаю вам использовать селектор css следующим образом:

nextPageSelect = '.hd-pagination__link::attr(href)'

Это даст вам ссылки вместо всего элемента HTML. Я предлагаю подробнее изучить css селекторы здесь .

Во-вторых, логически возникает проблема с вашим кодом.

next_page = response.css(nextPageSelect).getall()

этот кусок кода получает список всех ссылок «следующая страница» на текущей странице, но вы рассматриваете весь список как одну ссылку. Я предлагаю for l oop. Примерно так:

   if next_pages:
    for page in next_pages:
        yield scrapy.Request(
            response.urljoin(page),
            callback=self.parse
        )

Теперь, продолжая, я думаю, чтобы лучше использовать функции параллелизма и параллелизма Scrapy, вы можете захотеть вернуть список 'scrapy.Requests' вместо выполнения yield за каждый запрос, который вы найдете. Итак, подведем итог:

nextPageSelect = '.hd-pagination__link::attr(href)'
next_pages = response.css(nextPageSelect).getall()
requests = []
if next_pages:
    for page in next_pages:
        requests.append(scrapy.Request(
            response.urljoin(page),
            callback=self.parse
        ))
return requests

Удачи!

2 голосов
/ 21 февраля 2020

Вот некоторый рабочий код для того, что вы хотите сделать:

import scrapy
from urllib.parse import urlsplit, urljoin

class HomedepotSpider(scrapy.Spider):
    name = 'homedepot'
    start_urls = ['https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=0']

    def parse(self, response):

        # Here you do something with your items

        next_page = response.css('a.hd-pagination__link[title=Next]::attr(href)').get()
        if next_page is not None:
            o = urlsplit(response.url)
            base_url = f'{o.scheme}://{o.netloc}'
            next_page_url = urljoin(base_url,next_page)
            yield response.follow(next_page_url, callback=self.parse)

Основные моменты, на которые я хотел бы указать вам в этом коде:

  1. Проверьте селектор на следующая страница Он проверяет атрибут title и выбирает только элемент с заголовком «Next». То есть идентифицировать последнюю кнопку в нумерации страниц. Я не уверен, что в вашем примере указана правильная кнопка
  2. На следующей странице вы видите относительный URL. Для этого используйте urljoin, чтобы получить базовую часть текущего URL (response.url), а затем добавьте к этому относительному значению, которое вы получаете, с помощью urljoin
  3. Получив URL следующей страницы, вы можете просто используйте response.follow, чтобы указать пауку, чтобы добавить этот URL с выбранным обратным вызовом в список URL для сканирования

Также здесь есть журналы Scrapy, показывающие, что он просканировал 31 страницу. Это то, что вы должны получить, если выполните его

2020-02-21 10:42:04 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 44799,
 'downloader/request_count': 31,
 'downloader/request_method_count/GET': 31,
 'downloader/response_bytes': 1875031,
 'downloader/response_count': 31,
 'downloader/response_status_count/200': 31,
 'dupefilter/filtered': 1,
 'elapsed_time_seconds': 13.690273,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2020, 2, 21, 10, 42, 4, 145686),
 'log_count/DEBUG': 32,
 'log_count/INFO': 10,
 'memusage/max': 52195328,
 'memusage/startup': 52195328,
 'request_depth_max': 31,
 'response_received_count': 31,
 'scheduler/dequeued': 31,
 'scheduler/dequeued/memory': 31,
 'scheduler/enqueued': 31,
 'scheduler/enqueued/memory': 31,
 'start_time': datetime.datetime(2020, 2, 21, 10, 41, 50, 455413)}
2020-02-21 10:42:04 [scrapy.core.engine] INFO: Spider closed (finished)

Надеюсь, это поможет !!

1 голос
/ 14 февраля 2020

Попробуйте этот подход:

Получить номер текущей страницы и, используя его в качестве ссылки, получить номер следующей страницы, а затем использовать его в URL после умножения на счетчик

try:
    nextpage_number = response.xpath("//ul[contains(@class,'hd-pagination')]/li/a[contains(@class,'active ')]/ancestor::li[1]/following-sibling::li[1]/a/@title")[0].extract()
    current_url_stip = re.search( r"(.+Nao=)\d+", response.url)
    new_url = "%s=%s" % ( current_url_stip.group(1), nextpage_number * 24 )
    yield scrapy.Request(new_url, meta=response.meta)
except:
    pass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...