如何在puppeteer中打印控制台输出,使其与浏览器中显示的一样?

12

我一直看到这个错误的代码

page.on('console', msg => console.log(msg.text()));

那个失败了

console.log('Hello %s', 'World');
产生
Hello World     // browser
Hello %s World  // puppeteer

好的,所以我想也许我可以做到这一点

page.on('console', msg => console.log(...msg.args()));

不对:它会输出一个庞大的JSHandle对象。

好的,那么也许

page.on('console', msg => console.log(...msg.args().map(a => a.toString());

不行:那会输出

JSHandle: Hello %s JSHandle: World

我想我可以通过删除前9个字符来解决它。

我还尝试过

page.on('console', msg => console.log(...msg.args().map(a => a.jsonValue())));

不行:那会打印出来

Promise { <pending> } Promise { <pending> }

好的,那怎么样?

page.on('console', async(msg) => {
  const args = Promise.all(msg.args().map(a => a.jsonValue()));
  console.log(...args);
});

不对,那会打印

UnhandledPromiseRejectionWarning: TypeError: Found non-callable @@iterator
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 95)

再试一次

page.on('console', async(msg) => {
  const args = Promise.all(msg.args().map(async(a) => {
    return await a.jsonValue();
  }));
  console.log(...args);
});

与之前相同

UnhandledPromiseRejectionWarning: TypeError: Found non-callable @@iterator
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a 

我甚至跟踪了msg.text(),但它只是返回一个预制的字符串,所以现在使用它已经太迟了。

如何在Puppeteer中获得与浏览器的console.log相同的输出结果?


附注:如上所述,此方法适用于Puppeteer 1.20.0。

  page.on('console', (msg) => {
    console.log(...msg.args().map(v => v.toString().substr(9)));
  });

但显然这是一个hack,我期望它在某个时候会出现问题,因此正在寻找正确的解决方案。


也许我只需要提交一个错误报告......鉴于 msg.text 是错误的,问题可能更深入。 - gman
任何从浏览器传递到节点或从节点传递到浏览器的内容都会被序列化。因此,%s和其他任何东西可能都不起作用。 - Md. Abu Taher
如果我能获取原始参数,那么我就可以使用它们调用console.log。但是如上所述,我的尝试获取原始参数失败了。它们被前缀为“JSHandle:”。我可以使用msg.args().map(v => v.toString().substr(9))来获取它们,但这似乎是一种hack方法,因此我想知道正确的方法是什么。 - gman
2个回答

10
  page.on('console', async e => {
    const args = await Promise.all(e.args().map(a => a.jsonValue()));
    console.log(...args);
  });

或者

  page.on('console', async e => {
    const args = await Promise.all(e.args().map(a => a.jsonValue()));
    console[e.type() === 'warning' ? 'warn' : e.type()](...args);
  });

工作


1
你可以使用msg.args(),解决方法如下。
page.on('console', async msg => {
  const args = await msg.args()
  args.forEach(async (arg) => {
    const val = await arg.jsonValue()
    // value is serializable
    if (JSON.stringify(val) !== JSON.stringify({})) console.log(val)
    // value is unserializable (or an empty oject)
    else {
      const { type, subtype, description } = arg._remoteObject
      console.log(`type: ${type}, subtype: ${subtype}, description:\n ${description}`)
    }
  })
});

或者像这样,只打印Error
page.on('console', async msg => {
  // serialize my args the way I want
  const args = await Promise.all(msg.args.map(arg => arg.executionContext().evaluate(arg => {
    // I'm in a page context now. If my arg is an error - get me its message.
    if (arg instanceof Error)
      return arg.message;
    // return arg right away. since we use `executionContext.evaluate`, it'll return JSON value of
    // the argument if possible, or `undefined` if it fails to stringify it.
    return arg;
  }, arg)));
  console.log(...args);
});

参考:https://github.com/GoogleChrome/puppeteer/issues/3397 - Edi Imanto
这是有用的信息,但它实际上并没有回答所提出的问题。 - gman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接