javascript - 无法让 querySelectorAll 与 puppeteer 一起工作(返回未定义)
问题描述
我正在尝试使用超市的价格进行一些网络抓取。它与 node.js 和 puppeteer 一起使用。从接受 cookie 并单击“加载更多按钮”开始,我可以浏览网站。但是当我尝试使用 querySelectorAll 读取包含产品的 div 时,我被卡住了。即使我等待特定的 div 出现,它也会返回 undefined 。我错过了什么?
问题出在代码块的末尾。
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
返回一个NodeList,NodeLists只存在于前端,不存在后端。同样,NodeLists 包含 HTMLElements,它们也只存在于前端。
将所有需要使用仅存在于前端的数据的逻辑放在.evaluate
回调中,例如:
const numberOfDivs = await page.evaluate(_ => {
return document.querySelectorAll('div').length;
});
或者
const firstDivText = await page.evaluate(_ => {
return document.querySelector('div').textContent;
});
推荐阅读
- jms - 将 Spring 集成部署到 WebSphere ND 8.5.5
- java - 有没有一种很好的方法来检测 JTable 列之间的边界上的(双击)鼠标单击?
- python - 来自txt文件的输入和使用函数的简单绘图
- python - 如果与功能 API 一起使用,TensorFlow lambda 将增加一维
- electron - nodeIntegration:false 时的自定义电子标题栏问题
- html - Formik 没有显示在 nextjs 页面上?
- amazon-web-services - AWS 开发工具包 - 支持自定义信任库
- postgresql - 在 macOS 上安装 pg_partman
- node.js - nodejs + socket.io 通过 apache 代理
- c# - 将字符串拆分为两个字符对时出错(Codewars c#)