最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to get console.log output in Terminal via Headless Chrome Runtime.evaluate - Stack Overflow

programmeradmin2浏览0评论

I am following this issue post here:

But I cannot seem to get console.log output in the Mac Terminal. It's probably inside the Chrome Devtools window which I don't see.

So how do I get console.log output in Mac Terminal via Runtime.evaluate expression?

My code below:

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

  Page.loadEventFired(async () => {
    const result = await Runtime.evaluate({expression: 'console.log(\'aaa\')'});

    protocol.close();
    chrome.kill(); 
  });

})();

I am following this issue post here:

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

But I cannot seem to get console.log output in the Mac Terminal. It's probably inside the Chrome Devtools window which I don't see.

So how do I get console.log output in Mac Terminal via Runtime.evaluate expression?

My code below:

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

})();
Share Improve this question asked Aug 10, 2017 at 19:05 HP.HP. 19.9k56 gold badges159 silver badges258 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 11 +50

I've been doing some research on this; below are some of my findings:

When evaluating:

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

Result is always:

{ result: { type: 'undefined' } }

However, the following expression:

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

Returns:

{ result: { type: 'string', value: 'https://www.chromestatus.com/features' } }

Now if I evaluate the function without invoking it:

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

Result is set to:

{ result: { type: 'function', className: 'Function', description: 'function log() { [native code] }', objectId: '{"injectedScriptId":2,"id":1}' } }

So I did some more digging, and found that every time console.log is invoked when evaluated, the messageAdded event on the Console object is always fired.

So I went ahead and enabled the Console object and added a listener to the messageAdded event, and now I can successfully capture the console entry as expected.

This is what I did:

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 } }
*/

I got the details from Chrome DevTools Protocol Viewer - Console

From the documentation:

Console.messageAdded

Issued when new console message is added.

Hope this helps!

For those who want a less complicated way to get data from a page I'd recommend puppeteer. It has a much clearer higher-level API than chrome-remote-interface. The best feature in my opinion is its ability to accept javascript functions instead of strings for evaluation.

Let's say we want to fetch some data from API in context of a given page.

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();
})();
发布评论

评论列表(0)

  1. 暂无评论