better page load detection

This commit is contained in:
Antoni Sawicki
2026-03-10 02:07:14 -07:00
parent 619bd74891
commit fc15e4ea44
2 changed files with 42 additions and 2 deletions

View File

@@ -116,6 +116,46 @@ func ctxErr(err error, w io.Writer) {
fmt.Fprintln(w, "Created new context, try again")
}
func waitForRender() chromedp.ActionFunc {
return func(ctx context.Context) error {
timeout := *delay
if timeout > 5*time.Second {
timeout = 5 * time.Second
}
ch := make(chan struct{}, 1)
lctx, lcancel := context.WithCancel(ctx)
defer lcancel()
chromedp.ListenTarget(lctx, func(ev interface{}) {
if e, ok := ev.(*page.EventLifecycleEvent); ok && e.Name == "networkAlmostIdle" {
select {
case ch <- struct{}{}:
default:
}
}
})
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
select {
case <-ch:
return nil
default:
}
var ready bool
if err := chromedp.Evaluate(
`document.readyState === "complete" && Array.from(document.images).every(i => i.complete)`,
&ready,
).Do(ctx); err != nil {
return nil
}
if ready {
return nil
}
time.Sleep(100 * time.Millisecond)
}
return nil
}
}
// https://github.com/chromedp/chromedp/issues/979
func chromedpCaptureScreenshot(res *[]byte, h int64) chromedp.Action {
if res == nil {
@@ -154,7 +194,7 @@ func (rq *wrpReq) captureScreenshot() {
}
chromedp.Run(
ctx, emulation.SetDeviceMetricsOverride(int64(float64(rq.width)/rq.zoom), height, rq.zoom, false),
chromedp.Sleep(*delay), // TODO(tenox): find a better way to determine if page is rendered
waitForRender(),
)
// Capture screenshot...
ctxErr(chromedp.Run(ctx, chromedpCaptureScreenshot(&pngCap, rq.height)), rq.w)

2
wrp.go
View File

@@ -40,7 +40,7 @@ var (
defJpgQual = flag.Int64("q", 75, "Jpeg image quality, default 75%") // TODO: this should be form dropdown when jpeg is selected as image type
fgeom = flag.String("g", "1152x600x216", "Geometry: width x height x colors, height can be 0 for unlimited")
htmFnam = flag.String("ui", "wrp.html", "HTML template file for the UI")
delay = flag.Duration("s", 2*time.Second, "Delay/sleep after page is rendered and before screenshot is taken")
delay = flag.Duration("s", 5*time.Second, "Timeout for waiting for the page to render before screenshot")
userAgent = flag.String("ua", "jnrbsn", "override chrome user agent (jnrbsn=fetch from API, empty=default)")
browserPath = flag.String("b", "", "browser executable path (e.g., /Applications/Brave Browser.app/Contents/MacOS/Brave Browser)")
searchEng = flag.String("se", "https://duckduckgo.com/search?q=", "Search engine string")