chromedp – 如何从控制台中获取FCP等信息

huangapple go评论82阅读模式
英文:

chromedp - How to retrieve FCP and such from console

问题

我正在使用chromedp包构建一个个人爬虫。我想获取我的FCP(First Contentful Paint)和其他统计数据。不幸的是,我无法找到一种方法来实现这一点,然后我想到了从开发者控制台中提取它的方法。

不幸的是,在研究了两天后,我在互联网上找不到任何教程。

请问有人可以告诉我如何使用chromedp测量FCP和其他指标吗?

我尝试了以下代码,但返回一个错误:遇到了一个未定义的值。
但是,当我在浏览器的控制台中输入它时,它确实可以工作。

chromedp.EvaluateAsDevTools("const paintTimings = performance.getEntriesByType('paint');", nil),
chromedp.EvaluateAsDevTools("const fmp = paintTimings.find(({ name }) => name === \"first-contentful-paint\");", nil),
chromedp.EvaluateAsDevTools("console.log('First contentful paint at foo');", &jscript))

我发现我遇到的问题是,当执行console.log时,devtools也会返回一个未定义的值,这与Go所期望的不符。
有人知道如何解决这个问题吗?

英文:

I am building a personal scraper using the chromedp package. I would like to get my FCP(First Contentful Paint) and other stats. Unfortunately I am unable to find a way to do this, then I got the idea of extracting it from the developer console.

Unfortunately I am unable to find any tutorials on the internet after two days of fiddling around with it.

Can anyone tell me please how I can measure the FCP and other metrics with chromedp?

I tried this but it returns an error: encountered an undefined value.
But when I type it into my browser's console it actually does work.

chromedp.EvaluateAsDevTools("const paintTimings = performance.getEntriesByType('paint');", nil),
chromedp.EvaluateAsDevTools("const fmp = paintTimings.find(({ name }) => name === \"first-contentful-paint\");", nil),
chromedp.EvaluateAsDevTools("console.log('First contentful paint at foo');", &jscript))

I figured out that the problem I have is, that when a console.log is executed devtools also returns a undefined which collides with what Go expects.
Does anyone know how to fix this?

答案1

得分: 1

我不理解FCP是如何测量的。我将在下面提供一个从chromedp的角度工作的演示。

最好使用cdp Performance domain和/或cdp PerformanceTimeline domain,但正如我之前所说,我不了解FCP,也不知道如何使用它们。

package main

import (
	"context"
	"encoding/json"
	"log"

	"github.com/chromedp/chromedp"
)

type performancePaintTiming struct {
	EntryType string  `json:"entryType"`
	Name      string  `json:"name"`
	Duration  int     `json:"duration"`
	StartTime float64 `json:"startTime"`
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background(),
		// 启用调试模式以查看CDP消息。
		// 这有助于理解CDP的工作原理。
		// 但请不要在生产环境中启用它。
		chromedp.WithDebugf(log.Printf))
	defer cancel()

	// 我不知道为什么,但似乎Runtime.evaluate不再返回JSON对象,所以我必须将其字符串化为字符串。
	js := `
const paintTimings = performance.getEntriesByType('paint');
const fcp = paintTimings.find(({ name }) => name === "first-contentful-paint");
JSON.stringify(fcp);`

	var res string
	if err := chromedp.Run(ctx,
		chromedp.Navigate("https://www.bing.com/"),
		chromedp.EvaluateAsDevTools(js, &res),
	); err != nil {
		panic(err)
	}

	var fcp performancePaintTiming
	if err := json.Unmarshal([]byte(res), &fcp); err != nil {
		panic(err)
	}

	log.Printf("%#v", fcp)
}

参考资料:

  • 查看如何解析runtime.RemoteObject对象:https://github.com/chromedp/chromedp/blob/19b37c1b76b6a16d165e69e18756475ddc8f6432/eval.go#L66-L96
  • 查看关于encountered an undefined value的讨论:https://github.com/chromedp/chromedp/issues/526
英文:

I don't understand how FCP is measured. I will provide a demo that works from the perspective of chromedp below.

It would be better to use the cdp Performance domain and/or the cdp PerformanceTimeline domain, but as what I said before, I don't know FCP and I don't know how to use them.

package main

import (
	"context"
	"encoding/json"
	"log"

	"github.com/chromedp/chromedp"
)

type performancePaintTiming struct {
	EntryType string  `json:"entryType"`
	Name      string  `json:"name"`
	Duration  int     `json:"duration"`
	StartTime float64 `json:"startTime"`
}

func main() {
	ctx, cancel := chromedp.NewContext(context.Background(),
		// Enable the debug mode to see the CDP messages.
		// It's helpful to understand how CDP works.
		// But please don't enable it in Production Environment.
		chromedp.WithDebugf(log.Printf))
	defer cancel()

	// I don't know why but it seems that Runtime.evaluate does not return
	// JSON object any more, so I have to stringified it into a string.
	js := `
const paintTimings = performance.getEntriesByType('paint');
const fcp = paintTimings.find(({ name }) => name === "first-contentful-paint");
JSON.stringify(fcp);`

	var res string
	if err := chromedp.Run(ctx,
		chromedp.Navigate("https://www.bing.com/"),
		chromedp.EvaluateAsDevTools(js, &res),
	); err != nil {
		panic(err)
	}

	var fcp performancePaintTiming
	if err := json.Unmarshal([]byte(res), &fcp); err != nil {
		panic(err)
	}

	log.Printf("%#v", fcp)
}

References:

huangapple
  • 本文由 发表于 2022年11月16日 18:42:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/74459066.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定