我想将NodeList转换为对象。
H1是object.name
,依此类推。
我仍然无法理解page.evaluate()
的确切行为。
这就是我需要的:
这是我的尝试之一,但是gp
始终未定义:
await page.waitForNavigation();
const selG = 'body > div.content-home > div > div.box > div > div:nth- child(2) > div.col-md-12.no-padding > div:nth-child(4) > div:nth-child(2) > div.col-xs-12';
await page.waitForSelector(selG);
const g = await page.evaluate( (selG) => {
let gp = document.querySelector(selG); //null
let n = Array.from(gp.querySelectorAll('h1'), element => element.textContent);
console.log(n[0]);
return n;
});
最佳答案
page.evaluate()
运行您将其直接传递到浏览器中的函数,它没有启动Puppetter的NodeJS脚本的作用域(访问变量)。
要完全理解,请尝试以下操作:
1-按原样复制您的函数
2-将其包装到一个自调用函数([your-function])()
中,结果如下(我又添加了一个console.log(selG);
行)
((selG) => {
console.log(selG); // I added this line
let gp = document.querySelector(selG);
let n = Array.from(gp.querySelectorAll('h1'), element => element.textContent);
console.log(n[0]);
return n;
})()
3-将其直接粘贴到devtools控制台中
这样一来,(从理解的角度来看)您正在做的事更少,而
page.evaluate()
的作用就是运行将其直接传递给浏览器的功能。结果如何?它是
Cannot read property 'querySelectorAll' of null
,因为如您所述,gp
为空。但是请专心于我添加的
console.log(selG);
...它记录undefined
...这是个大问题!为什么会发生?
看一下函数本身,
selG
变量不存在,因此let gp = document.querySelector(selG);
不能返回任何内容。 selG
已定义为用于启动Puppeteer的脚本,但是传递给page.evaluate()
的函数将在浏览器中运行,而不是在Node执行上下文中运行。直接引用Puppeteer文档
page.evaluate(pageFunction,... args)
pageFunction在页面上下文中要评估的函数
... args 传递给pageFunction的参数
使用第二个其余的
args
(由Grant告知)将selG
变量传递给函数。遵循原始代码进行一些更改
await page.waitForNavigation();
const selG = 'body > div.content-home > div > div.box > div > div:nth- child(2) > div.col-md-12.no-padding > div:nth-child(4) > div:nth-child(2) > div.col-xs-12';
await page.waitForSelector(selG);
const g = await page.evaluate( (SELECTOR) => {
let gp = document.querySelector(SELECTOR);
let n = Array.from(gp.querySelectorAll('h1'), element => element.textContent);
console.log(n[0]);
return n;
}, selG);
请注意:
我将
selG
变量(最后一行)传递给pageFunction
(您的函数)pageFunction
接收一个变量并将其存储到SELECTOR
变量中pageFunction
比消耗收到的SELECTOR
总结一下:传递给
page.evaluate()
的函数不能使用在其外部声明的变量,因为它将被运行到浏览器中,该上下文与NodeJS脚本分离(旨在启动Puppeteer本身)。试试我的代码,它应该没有任何变化。
让我知道是否足够清楚。
奖金
请记住,如果要使用一些与DOM相关的数据,则至少可以使用三种不同的方法来执行相同的操作。
在下面,您可以找到我的示例,在该示例中,我想读取页面中找到的第一个链接的
href
属性。第一个示例像您一样使用page.evaluate()
,后两个示例向您展示了使用其他一些Puppeteer API的不同方法。const SELECTOR = '[href]:not([href=""])';
let link;
// compare the three following examples, they all do the same
link = await page.evaluate((sel) =>
document.querySelector(sel).getAttribute('href')
, SELECTOR);
link = await page.$eval(SELECTOR, el => el.getAttribute('href'));
link = await page.$(SELECTOR).getProperty('href').jsonValue();
关于javascript - Node.js/Puppeteer-JS对象的DOM NodeList,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52918634/