无法让 querySelectorAll 与 puppeteer 一起工作(returns 未定义)
Cannot get querySelectorAll to work with puppeteer (returns undefined)
我正在尝试使用超市的价格进行网络抓取。它与 node.js 和木偶操纵者一起使用。我可以通过接受 cookie 并单击“加载更多按钮”开始浏览网站。但是当我尝试阅读包含带有 querySelectorAll 的产品的 div 时,我卡住了。它 returns 未定义,即使我等待特定的 div 出现。我错过了什么?
问题出在代码块的末尾。
const { product } = require("puppeteer");
const scraperObjectAll = {
url: 'https://www.bilkatogo.dk/s/?query=',
async scraper(browser) {
let page = await browser.newPage();
console.log(`Navigating to ${this.url}`);
await page.goto(this.url);
// accept cookies
await page.evaluate(_ => {
CookieInformation.submitAllCategories();
});
var productsRead = 0;
var productsTotal = Number.MAX_VALUE;
while (productsRead < 100) {
// Wait for the required DOM to be rendered
await page.waitForSelector('button.btn.btn-dark.border-radius.my-3');
// Click button to read more products
await page.evaluate(_ => {
document.querySelector("button.btn.btn-dark.border-radius.my-3").click()
});
// Wait for it to load the new products
await page.waitForSelector('div.col-10.col-sm-4.col-lg-2.text-center.mt-4.text-secondary');
// Get number of products read and total
const loadProducts = await page.evaluate(_ => {
let p = document.querySelector("div.col-10.col-sm-4.col-lg-2").innerText.replace("INDLÆS FLERE", "").replace("Du har set ","").replace(" ", "").replace(/(\r\n|\n|\r)/gm,"").split("af ");
return p;
});
console.log("Products (read/total): " + loadProducts);
productsRead = loadProducts[0];
productsTotal = loadProducts[1];
// Now waiting for a div element
await page.waitForSelector('div[data-productid]');
const getProducts = await page.evaluate(_ => {
return document.querySelectorAll('div');
});
// PROBLEM HERE!
// Cannot convert undefined or null to object
console.log("LENGTH: " + Array.from(getProducts).length);
}
传递给 page.evaluate
的回调在 模拟页面 上下文中运行,不在 节点脚本的标准范围内.如果没有仔细考虑,表达式不能在页面和 Node 脚本之间传递:最重要的是,如果某些东西不可序列化(转换为普通 JSON),它就不能被传输。
querySelectorAll
returns一个NodeList,NodeList只存在于前端,不存在于后端。同样,NodeLists包含HTMLElements,同样只存在于前端。
将所有需要使用仅存在于前端的数据的逻辑放在.evaluate
回调中,例如:
const numberOfDivs = await page.evaluate(_ => {
return document.querySelectorAll('div').length;
});
或
const firstDivText = await page.evaluate(_ => {
return document.querySelector('div').textContent;
});
我正在尝试使用超市的价格进行网络抓取。它与 node.js 和木偶操纵者一起使用。我可以通过接受 cookie 并单击“加载更多按钮”开始浏览网站。但是当我尝试阅读包含带有 querySelectorAll 的产品的 div 时,我卡住了。它 returns 未定义,即使我等待特定的 div 出现。我错过了什么?
问题出在代码块的末尾。
const { product } = require("puppeteer");
const scraperObjectAll = {
url: 'https://www.bilkatogo.dk/s/?query=',
async scraper(browser) {
let page = await browser.newPage();
console.log(`Navigating to ${this.url}`);
await page.goto(this.url);
// accept cookies
await page.evaluate(_ => {
CookieInformation.submitAllCategories();
});
var productsRead = 0;
var productsTotal = Number.MAX_VALUE;
while (productsRead < 100) {
// Wait for the required DOM to be rendered
await page.waitForSelector('button.btn.btn-dark.border-radius.my-3');
// Click button to read more products
await page.evaluate(_ => {
document.querySelector("button.btn.btn-dark.border-radius.my-3").click()
});
// Wait for it to load the new products
await page.waitForSelector('div.col-10.col-sm-4.col-lg-2.text-center.mt-4.text-secondary');
// Get number of products read and total
const loadProducts = await page.evaluate(_ => {
let p = document.querySelector("div.col-10.col-sm-4.col-lg-2").innerText.replace("INDLÆS FLERE", "").replace("Du har set ","").replace(" ", "").replace(/(\r\n|\n|\r)/gm,"").split("af ");
return p;
});
console.log("Products (read/total): " + loadProducts);
productsRead = loadProducts[0];
productsTotal = loadProducts[1];
// Now waiting for a div element
await page.waitForSelector('div[data-productid]');
const getProducts = await page.evaluate(_ => {
return document.querySelectorAll('div');
});
// PROBLEM HERE!
// Cannot convert undefined or null to object
console.log("LENGTH: " + Array.from(getProducts).length);
}
传递给 page.evaluate
的回调在 模拟页面 上下文中运行,不在 节点脚本的标准范围内.如果没有仔细考虑,表达式不能在页面和 Node 脚本之间传递:最重要的是,如果某些东西不可序列化(转换为普通 JSON),它就不能被传输。
querySelectorAll
returns一个NodeList,NodeList只存在于前端,不存在于后端。同样,NodeLists包含HTMLElements,同样只存在于前端。
将所有需要使用仅存在于前端的数据的逻辑放在.evaluate
回调中,例如:
const numberOfDivs = await page.evaluate(_ => {
return document.querySelectorAll('div').length;
});
或
const firstDivText = await page.evaluate(_ => {
return document.querySelector('div').textContent;
});