Инкрементная пагинация в Scrapy / Python - PullRequest
0 голосов
/ 15 февраля 2019

Я столкнулся с проблемой пейджинга со Scrapy.Обычно я успешно использовал следующий код

next_page = response.xpath("//div//div[4]//ul[1]//li[10]//a[1]//@href").extract_first()
    if next_page is not None:
        yield scrapy.Request(url = response.urljoin(next_page), callback=self.parse)

Оказывается, в этой попытке я наткнулся на сайт, который использует блоки по 5 страниц.См. Изображение ниже.

enter image description here

Итак, после захвата первых 5 страниц Scrapy переходит на предпоследнюю страницу (526).

Структура подкачки имеет следующую логику:

https://www.example.com -1-data.html

И она увеличивается численно.Может кто-нибудь помочь мне с инкрементным запросом (на основе адреса примера) для этой нумерации страниц?

Ответы [ 2 ]

0 голосов
/ 16 февраля 2019

Для извлечения всех данных со всех страниц навигации вы можете использовать Scrapy LinkExtractor в правилах.

1 Использовать RegExp

rules = {
    Rule(LinkExtractor(allow='.*part-of-url/page-nav/page.*'), callback='parse_page', follow=True)
}

2 Использовать XPath

rules = {
        Rule(LinkExtractor(allow=(), restrict_xpaths='//ul[@class="nav-block"]'), callback='parse_page', follow=True)
    }
0 голосов
/ 16 февраля 2019

Когда дело доходит до нумерации страниц, оптимальный подход действительно зависит от того, какой тип нумерации используется.

Если вы:

  • знаете формат страницы URL, например, аргумент URL pageуказывает на какую страницу вы
  • знаете общее количество страниц

Тогда вы можете запланировать все страницы сразу:

def parse_listings_page1(self, response):
    """
    here parse first page, schedule all other pages at once!
    """
    # e.g. 'http://shop.com/products?page=1'
    url = response.url
    # e.g. 100
    total_pages = int(response.css('.last-page').extract_first())

    # schedule every page at once! 
    for page in range(2, total_pages + 1):
        page_url = add_or_replace_parameter(url, 'page', page)
        yield Request(page_url, self.parse_listings)
    # don't forget to also parse listings on first page!
    yield from self.parse_listings(response)


def parse_listings(self, response):
    for url in response.css('.listing::attr(href)'):
        yield Request(url, self.parse_product)

Огромные преимущества этого подходаскорость - здесь вы можете использовать асинхронную логику и сканировать все страницы одновременно!

В качестве альтернативы.

Если вы:

  • не знаете ничего, кроме следующей страницыURL-адрес находится на странице

Затем вы должны запланировать синхронное планирование страниц 1 на 1:

def parse(self, response):

    for product in response.css('.product::attr(href)'):
        yield Request(product, self.parse_product)

    next_page = response.css('.next-page::attr(href)').extract_first()
    if next_page:
        yield Request(next_page, self.parse)
    else:
        print(f'last page reached: {response.url}')

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...