如何通过 Headless Chrome Runtime.evaluate 在终端中获得 console.log 输出
How to get console.log output in Terminal via Headless Chrome Runtime.evaluate
我正在关注此问题post:
https://github.com/cyrus-and/chrome-remote-interface/issues/105
但我似乎无法在 Mac 终端中获得 console.log
输出。它可能在我没看到的 Chrome Devtools window 中。
那么如何通过 Runtime.evaluate 表达式在 Mac 终端中获得 console.log 输出?
我的代码如下:
const chromeLauncher = require('chrome-launcher');
const CDP = require('chrome-remote-interface');
const file = require('fs');
(async function() {
async function launchChrome() {
return await chromeLauncher.launch({
chromeFlags: [
'--headless',
'--disable-gpu'
]
});
}
const chrome = await launchChrome();
const protocol = await CDP({
port: chrome.port
});
const {
DOM,
Network,
Page,
Emulation,
Runtime
} = protocol;
await Promise.all([Network.enable(), Page.enable(), Runtime.enable(), DOM.enable()]);
Page.navigate({url: 'https://www.chromestatus.com/'});
Page.loadEventFired(async () => {
const result = await Runtime.evaluate({expression: 'console.log(\'aaa\')'});
protocol.close();
chrome.kill();
});
})();
我一直在研究这个问题;以下是我的一些发现:
评估时:
const result = await Runtime.evaluate({ expression: 'console.log("aaa")' });
结果总是:
{ result: { type: 'undefined' } }
但是,下面的表达式:
const result = await Runtime.evaluate({expression: 'window.location.toString()'});
Returns:
{ result: { type: 'string',
value: 'https://www.chromestatus.com/features' } }
现在,如果我在不调用函数的情况下求值:
const result = await Runtime.evaluate({ expression: 'console.log' });
结果设置为:
{ result: { type: 'function',
className: 'Function',
description: 'function log() { [native code] }',
objectId: '{"injectedScriptId":2,"id":1}' } }
所以我做了更多的挖掘,发现每次在评估时调用 console.log
,Console[=] 上的 messageAdded 事件48=] 对象总是被触发。
所以我继续启用控制台对象并为 messageAdded 事件添加了一个侦听器,现在我可以按预期成功捕获控制台条目。
这是我所做的:
const chromeLauncher = require('chrome-launcher');
const CDP = require('chrome-remote-interface');
const file = require('fs');
(async function() {
async function launchChrome() {
return await chromeLauncher.launch({
chromeFlags: [
'--headless',
'--disable-gpu'
]
});
}
const chrome = await launchChrome();
const protocol = await CDP({
port: chrome.port
});
const {
DOM,
Network,
Page,
Emulation,
Runtime,
Console
} = protocol;
await Promise.all([Network.enable(), Page.enable(), DOM.enable(), Runtime.enable(), Console.enable()]);
await Page.navigate({url: 'https://www.chromestatus.com/'});
// REMARKS: messageAdded is fired every time a new console message is added
Console.messageAdded((result) => {
console.log(result);
});
Page.loadEventFired(async () => {
const result = await Runtime.evaluate({ expression: 'console.log("aaa")' });
// REMARKS: When evaluating console.log, result.result.value is undefined.
console.log(result);
protocol.close();
chrome.kill();
});
})();
/* Output from listening on messageAdded:
{ message:
{ source: 'console-api',
level: 'log',
text: 'aaa',
url: '',
line: 1,
column: 9 } }
*/
我从 Chrome DevTools Protocol Viewer - Console
那里得到了详细信息
来自文档:
Console.messageAdded
Issued when new console message is added.
希望对您有所帮助!
对于那些想要以不太复杂的方式从页面获取数据的人,我推荐 puppeteer。它有比chrome-remote-interface更清晰的高层API。我认为最好的功能是它能够接受 javascript 函数而不是字符串进行评估。
假设我们想在给定页面的上下文中从 API 获取一些数据。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com/');
let result = await page.evaluate(async () => {
// here comes the code which gets executed in browser
return await fetch('index.html').then(response => response.text());
});
console.log(result);
await browser.close();
})();
我正在关注此问题post:
https://github.com/cyrus-and/chrome-remote-interface/issues/105
但我似乎无法在 Mac 终端中获得 console.log
输出。它可能在我没看到的 Chrome Devtools window 中。
那么如何通过 Runtime.evaluate 表达式在 Mac 终端中获得 console.log 输出?
我的代码如下:
const chromeLauncher = require('chrome-launcher');
const CDP = require('chrome-remote-interface');
const file = require('fs');
(async function() {
async function launchChrome() {
return await chromeLauncher.launch({
chromeFlags: [
'--headless',
'--disable-gpu'
]
});
}
const chrome = await launchChrome();
const protocol = await CDP({
port: chrome.port
});
const {
DOM,
Network,
Page,
Emulation,
Runtime
} = protocol;
await Promise.all([Network.enable(), Page.enable(), Runtime.enable(), DOM.enable()]);
Page.navigate({url: 'https://www.chromestatus.com/'});
Page.loadEventFired(async () => {
const result = await Runtime.evaluate({expression: 'console.log(\'aaa\')'});
protocol.close();
chrome.kill();
});
})();
我一直在研究这个问题;以下是我的一些发现:
评估时:
const result = await Runtime.evaluate({ expression: 'console.log("aaa")' });
结果总是:
{ result: { type: 'undefined' } }
但是,下面的表达式:
const result = await Runtime.evaluate({expression: 'window.location.toString()'});
Returns:
{ result: { type: 'string', value: 'https://www.chromestatus.com/features' } }
现在,如果我在不调用函数的情况下求值:
const result = await Runtime.evaluate({ expression: 'console.log' });
结果设置为:
{ result: { type: 'function', className: 'Function', description: 'function log() { [native code] }', objectId: '{"injectedScriptId":2,"id":1}' } }
所以我做了更多的挖掘,发现每次在评估时调用 console.log
,Console[=] 上的 messageAdded 事件48=] 对象总是被触发。
所以我继续启用控制台对象并为 messageAdded 事件添加了一个侦听器,现在我可以按预期成功捕获控制台条目。
这是我所做的:
const chromeLauncher = require('chrome-launcher');
const CDP = require('chrome-remote-interface');
const file = require('fs');
(async function() {
async function launchChrome() {
return await chromeLauncher.launch({
chromeFlags: [
'--headless',
'--disable-gpu'
]
});
}
const chrome = await launchChrome();
const protocol = await CDP({
port: chrome.port
});
const {
DOM,
Network,
Page,
Emulation,
Runtime,
Console
} = protocol;
await Promise.all([Network.enable(), Page.enable(), DOM.enable(), Runtime.enable(), Console.enable()]);
await Page.navigate({url: 'https://www.chromestatus.com/'});
// REMARKS: messageAdded is fired every time a new console message is added
Console.messageAdded((result) => {
console.log(result);
});
Page.loadEventFired(async () => {
const result = await Runtime.evaluate({ expression: 'console.log("aaa")' });
// REMARKS: When evaluating console.log, result.result.value is undefined.
console.log(result);
protocol.close();
chrome.kill();
});
})();
/* Output from listening on messageAdded:
{ message:
{ source: 'console-api',
level: 'log',
text: 'aaa',
url: '',
line: 1,
column: 9 } }
*/
我从 Chrome DevTools Protocol Viewer - Console
那里得到了详细信息来自文档:
Console.messageAdded
Issued when new console message is added.
希望对您有所帮助!
对于那些想要以不太复杂的方式从页面获取数据的人,我推荐 puppeteer。它有比chrome-remote-interface更清晰的高层API。我认为最好的功能是它能够接受 javascript 函数而不是字符串进行评估。
假设我们想在给定页面的上下文中从 API 获取一些数据。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com/');
let result = await page.evaluate(async () => {
// here comes the code which gets executed in browser
return await fetch('index.html').then(response => response.text());
});
console.log(result);
await browser.close();
})();