使用 Puppeteer 和 headless DOM 获取节点文本 Chrome
Getting DOM node text with Puppeteer and headless Chrome
我正在尝试使用无头 Chrome 和 Puppeteer 来 运行 我们的 Javascript 测试,但我无法从页面中提取结果。基于 , it looks like I should use page.evaluate()
。该部分甚至有一个看起来像我需要的示例。
const bodyHandle = await page.$('body');
const html = await page.evaluate(body => body.innerHTML, bodyHandle);
await bodyHandle.dispose();
作为一个完整的示例,我尝试将其转换为一个脚本,该脚本将从我在 Stack Overflow 上的用户个人资料中提取我的名字。我们的项目使用的是 Node 6,所以我将 await
表达式转换为使用 .then()
.
const puppeteer = require('puppeteer');
puppeteer.launch().then(function(browser) {
browser.newPage().then(function(page) {
page.goto('https://whosebug.com/users/4794').then(function() {
page.$('h2.user-card-name').then(function(heading_handle) {
page.evaluate(function(heading) {
return heading.innerText;
}, heading_handle).then(function(result) {
console.info(result);
browser.close();
}, function(error) {
console.error(error);
browser.close();
});
});
});
});
});
当我 运行 那个时,我得到这个错误:
$ node get_user.js
TypeError: Converting circular structure to JSON
at Object.stringify (native)
at args.map.x (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/helper.js:30:43)
at Array.map (native)
at Function.evaluationString (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/helper.js:30:29)
at Frame.<anonymous> (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:376:31)
at next (native)
at step (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:355:24)
at Promise (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:373:12)
at fn (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:351:10)
at Frame._rawEvaluate (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:375:3)
问题似乎在于将输入参数序列化为 page.evaluate()
。我可以传入字符串和数字,但不能传入元素句柄。这个例子是错误的,还是节点 6 有问题?如何提取 DOM 节点的文本?
我找到了解决这个问题的三种方法,具体取决于提取的复杂程度。最简单的选项是我没有注意到的相关函数:page.$eval()
。它基本上做了我想做的事情:结合 page.$()
和 page.evaluate()
。这是一个有效的例子:
const puppeteer = require('puppeteer');
puppeteer.launch().then(function(browser) {
browser.newPage().then(function(page) {
page.goto('https://whosebug.com/users/4794').then(function() {
page.$eval('h2.user-card-name', function(heading) {
return heading.innerText;
}).then(function(result) {
console.info(result);
browser.close();
});
});
});
});
这给了我预期的结果:
$ node get_user.js
Don Kirkby top 2% overall
本想提炼出更复杂的东西,但最终发现评估函数是运行在页面的上下文中。这意味着您可以使用页面中加载的任何工具,然后来回发送字符串和数字。在这个例子中,我在字符串中使用 jQuery 来提取我想要的内容:
const puppeteer = require('puppeteer');
puppeteer.launch().then(function(browser) {
browser.newPage().then(function(page) {
page.goto('https://whosebug.com/users/4794').then(function() {
page.evaluate("$('h2.user-card-name').text()").then(function(result) {
console.info(result);
browser.close();
});
});
});
});
这给了我完整的空白结果:
$ node get_user.js
Don Kirkby
top 2% overall
在我的真实脚本中,我想提取几个节点的文本,所以我需要一个函数而不是一个简单的字符串:
const puppeteer = require('puppeteer');
puppeteer.launch().then(function(browser) {
browser.newPage().then(function(page) {
page.goto('https://whosebug.com/users/4794').then(function() {
page.evaluate(function() {
return $('h2.user-card-name').text();
}).then(function(result) {
console.info(result);
browser.close();
});
});
});
});
这给出了完全相同的结果。现在我需要添加错误处理,并可能减少缩进级别。
使用 await/async
and $eval
,语法如下所示:
await page.goto('https://whosebug.com/users/4794')
const nameElement = await context.page.$eval('h2.user-card-name', el => el.text())
console.log(nameElement)
我使用以下方法取得了成功:
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto(url);
await page.waitFor(2000);
let html_content = await page.evaluate(el => el.innerHTML, await page.$('.element-class-name'));
console.log(html_content);
} catch (err) {
console.log(err);
}
希望对您有所帮助。
我使用 page.$eval
const text = await page.$eval('h2.user-card-name', el => el.innerText );
console.log(text);
我正在尝试使用无头 Chrome 和 Puppeteer 来 运行 我们的 Javascript 测试,但我无法从页面中提取结果。基于 page.evaluate()
。该部分甚至有一个看起来像我需要的示例。
const bodyHandle = await page.$('body');
const html = await page.evaluate(body => body.innerHTML, bodyHandle);
await bodyHandle.dispose();
作为一个完整的示例,我尝试将其转换为一个脚本,该脚本将从我在 Stack Overflow 上的用户个人资料中提取我的名字。我们的项目使用的是 Node 6,所以我将 await
表达式转换为使用 .then()
.
const puppeteer = require('puppeteer');
puppeteer.launch().then(function(browser) {
browser.newPage().then(function(page) {
page.goto('https://whosebug.com/users/4794').then(function() {
page.$('h2.user-card-name').then(function(heading_handle) {
page.evaluate(function(heading) {
return heading.innerText;
}, heading_handle).then(function(result) {
console.info(result);
browser.close();
}, function(error) {
console.error(error);
browser.close();
});
});
});
});
});
当我 运行 那个时,我得到这个错误:
$ node get_user.js
TypeError: Converting circular structure to JSON
at Object.stringify (native)
at args.map.x (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/helper.js:30:43)
at Array.map (native)
at Function.evaluationString (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/helper.js:30:29)
at Frame.<anonymous> (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:376:31)
at next (native)
at step (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:355:24)
at Promise (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:373:12)
at fn (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:351:10)
at Frame._rawEvaluate (/mnt/data/don/git/Kive/node_modules/puppeteer/node6/FrameManager.js:375:3)
问题似乎在于将输入参数序列化为 page.evaluate()
。我可以传入字符串和数字,但不能传入元素句柄。这个例子是错误的,还是节点 6 有问题?如何提取 DOM 节点的文本?
我找到了解决这个问题的三种方法,具体取决于提取的复杂程度。最简单的选项是我没有注意到的相关函数:page.$eval()
。它基本上做了我想做的事情:结合 page.$()
和 page.evaluate()
。这是一个有效的例子:
const puppeteer = require('puppeteer');
puppeteer.launch().then(function(browser) {
browser.newPage().then(function(page) {
page.goto('https://whosebug.com/users/4794').then(function() {
page.$eval('h2.user-card-name', function(heading) {
return heading.innerText;
}).then(function(result) {
console.info(result);
browser.close();
});
});
});
});
这给了我预期的结果:
$ node get_user.js
Don Kirkby top 2% overall
本想提炼出更复杂的东西,但最终发现评估函数是运行在页面的上下文中。这意味着您可以使用页面中加载的任何工具,然后来回发送字符串和数字。在这个例子中,我在字符串中使用 jQuery 来提取我想要的内容:
const puppeteer = require('puppeteer');
puppeteer.launch().then(function(browser) {
browser.newPage().then(function(page) {
page.goto('https://whosebug.com/users/4794').then(function() {
page.evaluate("$('h2.user-card-name').text()").then(function(result) {
console.info(result);
browser.close();
});
});
});
});
这给了我完整的空白结果:
$ node get_user.js
Don Kirkby
top 2% overall
在我的真实脚本中,我想提取几个节点的文本,所以我需要一个函数而不是一个简单的字符串:
const puppeteer = require('puppeteer');
puppeteer.launch().then(function(browser) {
browser.newPage().then(function(page) {
page.goto('https://whosebug.com/users/4794').then(function() {
page.evaluate(function() {
return $('h2.user-card-name').text();
}).then(function(result) {
console.info(result);
browser.close();
});
});
});
});
这给出了完全相同的结果。现在我需要添加错误处理,并可能减少缩进级别。
使用 await/async
and $eval
,语法如下所示:
await page.goto('https://whosebug.com/users/4794')
const nameElement = await context.page.$eval('h2.user-card-name', el => el.text())
console.log(nameElement)
我使用以下方法取得了成功:
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto(url);
await page.waitFor(2000);
let html_content = await page.evaluate(el => el.innerHTML, await page.$('.element-class-name'));
console.log(html_content);
} catch (err) {
console.log(err);
}
希望对您有所帮助。
我使用 page.$eval
const text = await page.$eval('h2.user-card-name', el => el.innerText );
console.log(text);