3

得到终端的console.log输出在这里,我下面这个问题后:如何通过无头的Chrome Runtime.evaluate

https://github.com/cyrus-and/chrome-remote-interface/issues/105

但我似乎无法得到console.log输出在Mac的终端。它可能在我看不到的Chrome Devtools窗口中。

所以我怎么通过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(); 
    }); 

})(); 

回答

2

我一直在做一些这方面的研究;下面是我的一些调查结果:

当评估:

const result = await Runtime.evaluate({ expression: 'console.log("aaa")' }); 

结果总是:

{结果:{类型: '未定义'}}

然而,下面的表达式:

const result = await Runtime.evaluate({expression: 'window.location.toString()'}); 

返回:

{结果:{类型: '串', 值: 'https://www.chromestatus.com/features'}}

现在,如果我计算函数,而不必调用它:

const result = await Runtime.evaluate({ expression: 'console.log' }); 

结果设置为:

{结果: {类型: '功能', 的className: '功能', 描述: '函数log(){[本地代码]}', 的ObjectID: '{ “injectedScriptId”:2 “ID”:1}'}}

所以我做了一些更多的挖掘,发现每次console.log调用计算时,该messageAdded的控制台对象事件总是被解雇。

所以我继续启用了控制台对象,并增加了一个监听器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

从文档:

控制台。消息已添加

添加新控制台消息时发出。

希望这有助于!

+0

上帝的母亲。为什么它必须是复杂的。谢谢!! –

+0

@惠普。大声笑,我确切地知道你的意思。当然,很高兴帮助!不要忘记奖励赏金。 :P – mscheker

0

对于那些希望以较简单的方式从页面获取数据的人,我推荐使用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(); 
})();