如何使用 Puppeteer 获取页数?
How to get number of pages using Puppeteer?
我是使用 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 页 ....)
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()
获取页面数组(=Tab)
Puppeteer 第一次绝对有 1 个选项卡。
由于默认情况下该站点上显示的页面数量的性质,这是一个困难的过程。但请耐心等待:我将向您展示您至少可以通过这个实现什么。
首先,您提供的网站在您可以循环浏览的项目列表下方一次列出 10 个页面。很抱歉,我不懂它使用的语言,所以我不知道是否有某个地方可以显示更多页面。因此,当您输入搜索文本时,它会显示如下:
但是,当您单击最后一个数字(数字 10)时,页面列表更新如下:
这使得查找总页数变得更加困难,因为没有 "jump" 到最后一页的选项(随后也没有跳回到第一页的选项)。稍后我将向您展示另一个执行此操作的网站示例。
针对您的情况,我建议您使用一些简单的数学方法来确定要列出的确切页数。将 puppeteer
告诉 "keep clicking the last available page number until you reach the end" 或类似的东西会变得太复杂了。但是我们可以通过执行几个简单的步骤来确定有多少页。
首先,您需要通过此元素获取搜索列表中返回的项目总数:
您可以通过执行以下代码来做到这一点:
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://whosebug.com/questions/tagged/puppeteer
现在滚动到页面底部,您会看到如下内容:
这是确定在一个简单的步骤中列出了多少页的理想选择,如下所示:
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
希望这里的内容对您的人偶学习之旅有所帮助!
将属性 footerTemplate 与 displayHeaderFooter 一起用于最初使用 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 类 用于将打印值注入其中:
// - 日期 格式化打印日期
// - 标题文档标题
// - url 文档位置
// - pageNumber 当前页码
// - 总页数 文档总页数
我是使用 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 页 ....)
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()
获取页面数组(=Tab)
Puppeteer 第一次绝对有 1 个选项卡。
由于默认情况下该站点上显示的页面数量的性质,这是一个困难的过程。但请耐心等待:我将向您展示您至少可以通过这个实现什么。
首先,您提供的网站在您可以循环浏览的项目列表下方一次列出 10 个页面。很抱歉,我不懂它使用的语言,所以我不知道是否有某个地方可以显示更多页面。因此,当您输入搜索文本时,它会显示如下:
但是,当您单击最后一个数字(数字 10)时,页面列表更新如下:
这使得查找总页数变得更加困难,因为没有 "jump" 到最后一页的选项(随后也没有跳回到第一页的选项)。稍后我将向您展示另一个执行此操作的网站示例。
针对您的情况,我建议您使用一些简单的数学方法来确定要列出的确切页数。将 puppeteer
告诉 "keep clicking the last available page number until you reach the end" 或类似的东西会变得太复杂了。但是我们可以通过执行几个简单的步骤来确定有多少页。
首先,您需要通过此元素获取搜索列表中返回的项目总数:
您可以通过执行以下代码来做到这一点:
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://whosebug.com/questions/tagged/puppeteer
现在滚动到页面底部,您会看到如下内容:
这是确定在一个简单的步骤中列出了多少页的理想选择,如下所示:
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
希望这里的内容对您的人偶学习之旅有所帮助!
将属性 footerTemplate 与 displayHeaderFooter 一起用于最初使用 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 类 用于将打印值注入其中:
// - 日期 格式化打印日期
// - 标题文档标题
// - url 文档位置
// - pageNumber 当前页码
// - 总页数 文档总页数