Gre*_*Ros 7 google-chrome chromium google-chrome-devtools puppeteer
我有一个在无头Chromium实例中运行的页面,我正在使用Node中的Puppeteer NPM包通过DevTools协议进行操作.
我正在向页面中注入一个脚本.在某些时候,我希望脚本给我回电话并向我发送一些信息(通过DevTools协议或其他方式暴露的某些事件).
做这个的最好方式是什么?如果可以使用Puppeteer完成它会很棒,但我并不反对让我的手弄脏并手动收听协议消息.
我知道我可以通过操纵DOM并监听DOM更改来实现这一点,但这听起来不是一个好主意.
如果脚本在一次调用中将所有数据发回,则最简单的方法是使用page.evaluate并从中返回Promise:
const dataBack = page.evaluate(`new Promise((resolve, reject) => {
setTimeout(() => resolve('some data'), 1000)
})`)
dataBack.then(value => { console.log('got data back', value) })
Run Code Online (Sandbox Code Playgroud)
这可以推广到两次发送数据等.对于发送回任意事件流,可能console.log会比DOM事件稍微少一点?至少它对Puppeteer来说非常容易:
page.on('console', message => {
if (message.text.startsWith('dataFromMyScript')) {
message.args[1].jsonValue().then(value => console.log('got data back', value))
}
})
page.evaluate(`setInterval(() => console.log('dataFromMyScript', {ts: Date.now()}), 1000)`)
Run Code Online (Sandbox Code Playgroud)
(该示例使用魔术前缀来区分这些日志消息与其他所有消息.)
好的,我发现了一种内置的方法来实现这一目标Puppeteer.Puppeteer定义一个名为的方法exposeFunction.
page.exposeFunction(name, puppeteerFunction)
Run Code Online (Sandbox Code Playgroud)
此方法window在页面对象上定义具有给定名称的函数.该功能在页面上是异步的.当它被调用时,puppeteerFunction你定义被执行为具有相同参数的回调.参数不是JSON序列化的,而是传递给JSHandles它们,因为它们暴露了对象本身.就个人而言,我选择在发送之前对值进行JSON序列化.
我已经查看了代码,它实际上只是通过发送控制台消息来工作,就像在Pasi的答案中一样,Puppeteer控制台钩子忽略了.但是,如果您直接听控制台(即通过管道stdout).您仍会看到它们以及常规消息.
由于控制台信息实际上是由WebSocket发送的,因此非常有效.我有点厌恶使用它,因为在大多数进程中,控制台通过stdout传输数据,这有问题.
async function example() {
const puppeteer = require("puppeteer");
let browser = await puppeteer.launch({
//arguments
});
let page = await browser.newPage();
await page.exposeFunction("callPuppeteer", function(data) {
console.log("Node receives some data!", data);
});
await page.goto("http://www.example.com/target");
}
Run Code Online (Sandbox Code Playgroud)
在页面的javascript中:
window.callPuppeteer(JSON.stringify({
thisCameFromThePage : "hello!"
}));
Run Code Online (Sandbox Code Playgroud)
DevTools协议支持类似的东西puppeteer.exposeFunction.
https://chromedevtools.github.io/devtools-protocol/tot/Runtime#method-addBinding
如果executionContextId为空,则在所有检查的上下文的全局对象上添加具有给定名称的绑定,包括稍后创建的绑定,绑定将在重新加载后继续存在.如果指定了executionContextId,则仅在给定执行上下文的全局对象上添加绑定.绑定函数只接受一个参数,这个参数应该是字符串,在任何其他输入的情况下,函数抛出异常.每个绑定函数调用都会生成Runtime.bindingCalled通知.
.
| 归档时间: |
|
| 查看次数: |
915 次 |
| 最近记录: |