Проблемы с получением следующей страницы при соскабливании с помощью скрапа - PullRequest
0 голосов
/ 17 февраля 2020

У меня есть код, который не сканирует нумерацию страниц, и я застрял.

Источник страницы:

https://www.levenhuk.bg/katalog/teleskopi/?page=1

Мой код:




import scrapy


class TelescopesSpider(scrapy.Spider):
    name = 'telescopes'
    allowed_domains = ['https://www.levenhuk.bg/']
    start_urls = ['https://www.levenhuk.bg/katalog/teleskopi/?page=1']
    download_delay = 3

    def parse(self, response):
        for product in response.xpath('//div[@class="catalog-item"]'):
            yield {

                # 'name': product.xpath('.//span[@itemprop="name" and contains(text(), "Levenhuk")]/text()').get(),
                'name': product.xpath('.//span[@itemprop="name"]/text()').get(),
                # 'price': product.xpath('.//div[@class="price"]/span/text()').get(),
                'price': product.xpath('.//span[@itemprop="price"]/text()').re_first(r'[0-9]+,[0-9]+'),
                'short_discr': product.xpath('.//div[@class="opis-item"]/p/strong/text()').get()

            }

            next_page_url = response.xpath('//*[@class="pagesCount"][1]//@href').get()
            if next_page_url is not None:
                yield scrapy.Request(response.urljoin(next_page_url))



Ответы [ 3 ]

3 голосов
/ 17 февраля 2020

Мне кажется, проблема в том, что вы не указываете callback в своем запросе на нумерацию страниц. Укажите функцию parse в качестве обратного вызова, и это должно работать. пожалуйста, прокомментируйте, если это все еще не работает.

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

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

    def parse(self, response):
        self.extract_item(response)
        next_page_urls = response.xpath('//*[@class="pagesCount"] [1]//@href').getall()
        if next_page_urls is not None:
            for url in next_page_urls:
                yield scrapy.Request(response.urljoin(url), callback=self.extract_item)

    def extract_item(self, response):
        for product in response.xpath('//div[@class="catalog-item"]'):
           yield {

            # 'name': product.xpath('.//span[@itemprop="name" and contains(text(), "Levenhuk")]/text()').get(),
            'name': product.xpath('.//span[@itemprop="name"]/text()').get(),
            # 'price': product.xpath('.//div[@class="price"]/span/text()').get(),
            'price': product.xpath('.//span[@itemprop="price"]/text()').re_first(r'[0-9]+,[0-9]+'),
            'short_discr': product.xpath('.//div[@class="opis-item"]/p/strong/text()').get()

        }

, поэтому теперь функция parse обрабатывает разбиение на страницы, а функция extract_item извлекает элементы для каждой страницы.

Изменяет allowed_domains, а также задает Pasindu .

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

Измените это на:

    allowed_domains = ['https://www.levenhuk.bg/']
    allowed_domains = ['levenhuk.bg'] 

Вам также необходимо изменить:

   next_page_url = response.xpath('//*[@class="pagesCount"][1]//@href').get()

Это будет работать только для первой страницы, для страницы 2,3,4 .., это извлечет ссылку на первую страницу.

, а также добавит обратный вызов, как упомянуто UzairAhmed.

0 голосов
/ 17 февраля 2020

Это немного сложно, поскольку обычно стандартная практика состоит в том, чтобы просто проверить, есть ли кнопка следующей страницы в al oop, пока ее нет.

Вот пример, так как кнопки следующей страницы нет мы можем выяснить общее количество страниц. Будет повторный запрос к page1, хотя с этим методом это не самая идеальная ситуация.

import scrapy


class TelescopesSpider(scrapy.Spider):
    name = 'telescopes'
    allowed_domains = ['https://www.levenhuk.bg/']
    start_urls = ['https://www.levenhuk.bg/katalog/teleskopi/?page=1']
    download_delay = 3

    def parse(self, response):
        total_pages = response.css('.pagesCount a::text')[-1].get()
        total_pages = int(total_pages)
        pages_str = str(total_pages)
        for i in range(1, total_pages):
            url = 'https://www.levenhuk.bg/katalog/teleskopi/?page={}'.format(pages_str)
            yield scrapy.Request(url, callback=self.parse_item, dont_filter=True)

    def parse_item(self, response):
        for product in response.xpath('//div[@class="catalog-item"]'):
           yield {
            'name': product.xpath('.//span[@itemprop="name"]/text()').get(),
            'price': product.xpath('.//span[@itemprop="price"]/text()').re_first(r'[0-9]+,[0-9]+'),
            'short_discr': product.xpath('.//div[@class="opis-item"]/p/strong/text()').get()
        }

Другой способ сделать это - просто посмотреть, сколько страниц существует, и перебрать ваш метод start_requests. следующим образом:

class TelescopesSpider(scrapy.Spider):
    name = 'telescopes'
    allowed_domains = ['https://www.levenhuk.bg/']
    start_urls = ['https://www.levenhuk.bg/katalog/teleskopi/?page={}']
    download_delay = 3

    def start_requests(self):
        for i in range(1, 14):
            yield scrapy.Request(self.start_urls[0].format(str(i)), callback=self.parse)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...