如何使用Puppeteer获取页面数量?

3

我是一个使用Puppeteer进行爬虫的初学者。我成功地爬取了以下网站。下面是从购物商城中提取特定产品名称的代码。

const express = require('express');
const puppeteer = require('puppeteer');
const app = express();

(async () => {

    const width = 1600, height = 1040;

    const option = { headless: true, slowMo: true, args: [`--window-size=${width},${height}`] };

    const browser = await puppeteer.launch(option);
    const page = await browser.newPage();
    const vp = {width: width, height: height};
    await page.setViewport(vp);

    const navigationPromise = page.waitForNavigation();

    // 네이버 스토어팜
    await page.goto('https://shopping.naver.com/home/p/index.nhn');
    await navigationPromise;
    await page.waitFor(2000);

    const textBoxId = 'co_srh_input';
    await page.type('.' + textBoxId, '양말', {delay: 100});
    await page.keyboard.press('Enter');

    await page.waitFor(5000);
    await page.waitForSelector('ul.goods_list');
    await page.addScriptTag({url: 'https://code.jquery.com/jquery-3.2.1.min.js'});

    const result = await page.evaluate(() => {

        const data = [];

        $('ul.goods_list > li._itemSection').each(function () {

            const title = $.trim($(this).find('div.info > a.tit').text());
            const price = $(this).find('div.info > .price .num').text();
            const image = $(this).find('div.img_area img').attr('src');

            data.push({ title, price, image })

        });

        return data;

    });

    console.log(result);
    await browser.close();

})();

app.listen(3000, () => console.log("Express!!!"));

我有一个问题。如果我想从多个页面获取信息,我该怎么做? 例如(第1页,第2页,第3页......)


每个页面都有自己的URL吧? - mihai
3个回答

3
使用属性footerTemplatedisplayHeaderFooter,以显示最初使用puppeteer API的页面。
await page.pdf({
  path: 'hacks.pdf',
  format: 'A4',
  displayHeaderFooter: true,
  footerTemplate: '<div><div class='pageNumber'></div> <div>/</div><div class='totalPages'></div></div>'
});

https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#pagepdfoptions

// footerTemplate:打印页脚的HTML模板。

// 必须是有效的HTML标记,其中包含以下CSS类,用于将打印值注入其中:

// - date:格式化后的打印日期

// - title:文档标题

// - url:文档位置

// - pageNumber:当前页面编号

// - totalPages:文档中的总页数


2

由于该网站默认显示许多页面,这是一个比较困难的问题。但请耐心等待:我将向您展示您至少可以使用此内容实现什么。

首先,您提供的网站在项目列表下方每次列出10页,您可以循环浏览它们。很抱歉,我不知道它所使用的语言,也就不知道是否有选项可显示更多页面。因此,当您输入搜索文本时,它显示如下:

列出了前十页

然而,当您单击最后一个数字(即数字10)时,页面列表会更新为以下内容:

动态添加更多页面

这样做使查找总页面数变得更加困难,因为没有“跳转”到最后一页的选项(随之也没有跳回第一页的选项)。稍后我将向您展示另一个执行此操作的网站示例。

在您的情况下,我建议您使用一些简单的数学方法来确定要列出多少页。告诉例如 Marionette去“一直点击最后一个可用页码,直到达到结束”或类似操作会变得过于复杂。但是我们可以通过执行几个简单的步骤来确定页面的数量。

首先,您需要通过此元素获取搜索列表中返回的项目总数:

结果总数

您可以通过执行以下代码来完成:

const totalItems = await page.$eval('._productSet_total', (items) => {
  // Remove the characters before the total number, leaving only the number in isolation
  const child = items.querySelector('em');
  items.removeChild(child);

  // Now remove all commas from the total number
  let finalItems = items.textContent.trim();
  while(finalItems.indexOf(',') > -1) {
    finalItems = finalItems.replace(',', '').trim();
  }
  return finalItems;
});
console.log(totalItems); // Outputs 4337903 (or something similar)

现在你已经知道了总数。下一步是确定每页要显示多少个项目。你可以通过计算当前页面上显示的项目数量来完成 - 如下所示:

const itemsPerPage = await page.$$eval('.goods_list li', (items) => {
  return items.length;
});
console.log(itemsPerPage); // Outputs 180 on my machine

现在,您已经知道了找到的所有项目数量以及每个页面要显示的项目数量。接下来就是简单的数学计算,确定需要多少页才能列出所有这些项目:

const pages = totalItems / itemsPerPage;
console.log(Math.ceil(pages));

就这样!由于网站本身设计不佳(实际上应该始终直接提供到第一页和/或最后一页的路线),所以这是一个相当困难的例子。

例如,如果您在Stack Overflow(这个非常棒的网站)中点击puppeteer标签,它将带您前往:https://stackoverflow.com/questions/tagged/puppeteer

现在滚动到页面底部,您将看到以下内容:

enter image description here

这非常理想,可以通过以下简单步骤确定列出了多少页:

const lastPage = await page.$$eval('div[class*="pager"] > a > span[class*="page-numbers"]', (spans) => {
  return spans[spans.length - 2].textContent;
});
console.log(lastPage); // Outputs 78

希望这里的内容能够帮助您在学习puppeteer的过程中更好地理解!


那是一个很棒的答案! - Vaviloff

0
  if (!this.browser) {
    this.browser = await puppeteer.launch(this.OPT)
    const pages: puppeteer.Page[] = await this.browser.pages()

    // close chromium by catching 'targetdestryed'
    this.browser.on('targetdestroyed', async () => {
      if (this.browser) {
        const pages: puppeteer.Page[] = await this.browser.pages()
        if (pages.length === 0) {
          process.exit(0)
        }
      }
    })
  }

以上是我用Typescript编写的代码。 你可以从browser.pages()获取页面(=选项卡)数组。 而且Puppeteer第一次绝对有1个选项卡。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接