我正在使用 Puppeteer 构建一个基本的网络爬虫,到目前为止,我可以从任何给定页面返回我需要的所有数据,但是当涉及分页时,我的爬虫会卡住(仅返回第一页)。
参见示例 - 这将返回前 20 本书的标题/价格,但不会查看其他 49 页的书籍。
只是寻找有关如何克服这个问题的指导 - 我在文档中看不到任何内容。
谢谢!
const puppeteer = require('puppeteer');
let scrape = async () => {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.goto('http://books.toscrape.com/');
const result = await page.evaluate(() => {
let data = [];
let elements = document.querySelectorAll('.product_pod');
for (var element of elements){
let title = element.childNodes[5].innerText;
let price = element.childNodes[7].children[0].innerText;
data.push({title, price});
}
return data;
});
browser.close();
return result;
};
scrape().then((value) => {
console.log(value);
});
说清楚。我正在关注这里的教程 - 该代码来自 codeburst.io 上的 Brandon Morelli! https://codeburst.io/a-guide-to-automating-scraping-the-web-with-javascript-chrome-puppeteer-node-js-b18efb9e9921
我正在阅读同一篇文章,以便自学如何使用 Puppeteer。 对您问题的简短回答是,您需要再引入一个循环来迭代在线图书目录中的所有可用页面。 我已完成以下步骤来收集所有书名和价格:
page.evaluate
部分,该函数以页面为参数与 Brandon Morelli 文章中的代码完全相同,但现在多了一个循环:
const puppeteer = require('puppeteer');
let scrape = async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('http://books.toscrape.com/');
var results = []; // variable to hold collection of all book titles and prices
var lastPageNumber = 50; // this is hardcoded last catalogue page, you can set it dunamically if you wish
// defined simple loop to iterate over number of catalogue pages
for (let index = 0; index < lastPageNumber; index++) {
// wait 1 sec for page load
await page.waitFor(1000);
// call and wait extractedEvaluateCall and concatenate results every iteration.
// You can use results.push, but will get collection of collections at the end of iteration
results = results.concat(await extractedEvaluateCall(page));
// this is where next button on page clicked to jump to another page
if (index != lastPageNumber - 1) {
// no next button on last page
await page.click('#default > div > div > div > div > section > div:nth-child(2) > div > ul > li.next > a');
}
}
browser.close();
return results;
};
async function extractedEvaluateCall(page) {
// just extracted same exact logic in separate function
// this function should use async keyword in order to work and take page as argument
return page.evaluate(() => {
let data = [];
let elements = document.querySelectorAll('.product_pod');
for (var element of elements) {
let title = element.childNodes[5].innerText;
let price = element.childNodes[7].children[0].innerText;
data.push({ title, price });
}
return data;
});
}
scrape().then((value) => {
console.log(value);
console.log('Collection length: ' + value.length);
console.log(value[0]);
console.log(value[value.length - 1]);
});
控制台输出:
...
{ title: 'In the Country We ...', price: '£22.00' },
... 900 more items ]
Collection length: 1000
{ title: 'A Light in the ...', price: '£51.77' }
{ title: '1,000 Places to See ...', price: '£26.08' }
我不会用
await page.waitFor(1000);
使用
await page.waitForSelector(selector)
其中选择器是您知道所有页面中都存在的东西。
使用这种方法,您不会遇到页面加载时间超过一秒的情况,例如互联网连接不稳定,并且您可以保证在使用评估时加载页面。