Scrapy / Python中的增量分页

时间:2019-02-15 20:07:59

标签: python scrapy

我遇到了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 :(得分:3)

关于分页,最佳方法实际上取决于所使用的分页类型。

如果您:

  • 了解网址页面格式 例如网址参数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)

此方法的巨大好处是速度-在这里,您可以采用异步逻辑并同时抓取所有页面!

或者。

如果您:

  • 页面上除了下一页网址外,什么都不知道

然后,您必须按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选择器选择正确的页面即可。

答案 1 :(得分:1)

要从所有导航页提取所有数据,可以在规则中使用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)
    }