【问题标题】:How to get console.log output in Terminal via Headless Chrome Runtime.evaluate如何通过 Headless Chrome Runtime.evaluate 在终端中获取 console.log 输出
【发布时间】:2017-08-10 19:05:28
【问题描述】:

我在这里关注这个问题:

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

但我似乎无法在 Mac 终端中获得 console.log 输出。它可能在我看不到的 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(); 
  });

})();

【问题讨论】:

    标签: javascript node.js google-chrome-devtools google-chrome-headless


    【解决方案1】:

    我一直在对此进行一些研究;以下是我的一些发现:

    评估时:

    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' });
    

    结果设置为:

    { 结果:{ 类型:'函数', 类名:'功能', 描述:'function log() { [native code] }', objectId: '{"injectedScriptId":2,"id":1}' } }

    所以我做了一些更多的挖掘,发现每次在评估时调用console.log,总是会触发 Console 对象上的 messageAdded 事件。 p>

    所以我继续启用控制台对象并为 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

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

    希望这会有所帮助!

    【讨论】:

    • 上帝之母。为什么一定要这么复杂。谢谢!!
    • @HP。大声笑,我完全明白你的意思。当然可以,很高兴能帮上忙!不要忘记奖励赏金。 :P
    【解决方案2】:

    对于那些希望以一种不太复杂的方式从页面获取数据的人,我推荐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();
    })();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多