v0.3.3

架構

最後更新


go-browser 由四個模組構成:路由決定用哪個瀏覽器,瀏覽器載入頁面,頁面轉成快照,快照轉成輸出;唯一的回頭路是被擋時的一次有頭重試。

系統概覽


graph TB
    subgraph Entry
        A[Fetch]
    end
    subgraph Routing
        B{Option.Headless}
        C{Visible 或 requiresSession,且 hasDisplay}
        D[headless 優先]
        E{isBlocked + hasDisplay}
    end
    subgraph Launcher
        F{SameSession}
        G[launchWithSnapshot:暫存 profile + Cookie]
        H[ensureBrowser:以 headless + UA 快取]
    end
    subgraph Pipeline
        I[load: Navigate + Settle]
        J[handleConsent]
        K[Scroll + Snapshots]
    end
    subgraph Output
        L[Merge / Readability]
        M[HTMLToMarkdown]
        N[HTMLToNode]
    end
    A --> B
    B -->|true| F
    B -->|false| C
    C -->|是:有頭| F
    C -->|否| D --> F
    F -->|是| G
    F -->|否| H
    G -->|ErrProfileNotFound| H
    G --> I
    H --> I --> J --> K --> L
    L --> M
    M -->|TypeJSON| N
    D -.->|結果 403 / 429 / 503| E
    E -->|是:有頭重試一次| F
  1. graph TB
  2. subgraph Entry
  3. A[Fetch]
  4. end
  5. subgraph Routing
  6. B{Option.Headless}
  7. C{Visible 或 requiresSession,且 hasDisplay}
  8. D[headless 優先]
  9. E{isBlocked + hasDisplay}
  10. end
  11. subgraph Launcher
  12. F{SameSession}
  13. G[launchWithSnapshot:暫存 profile + Cookie]
  14. H[ensureBrowser:以 headless + UA 快取]
  15. end
  16. subgraph Pipeline
  17. I[load: Navigate + Settle]
  18. J[handleConsent]
  19. K[Scroll + Snapshots]
  20. end
  21. subgraph Output
  22. L[Merge / Readability]
  23. M[HTMLToMarkdown]
  24. N[HTMLToNode]
  25. end
  26. A --> B
  27. B -->|true| F
  28. B -->|false| C
  29. C -->|是:有頭| F
  30. C -->|否| D --> F
  31. F -->|是| G
  32. F -->|否| H
  33. G -->|ErrProfileNotFound| H
  34. G --> I
  35. H --> I --> J --> K --> L
  36. L --> M
  37. M -->|TypeJSON| N
  38. D -.->|結果 403 / 429 / 503| E
  39. E -->|是:有頭重試一次| F

分層


層檔案職責對外
進入點與路由core/fetch.go模式選擇、被擋判定、重試決策、載入管線Fetch、Option、Viewport、Result、Error、TypeMarkdown、TypeHTML、TypeJSON
瀏覽器生命週期core/launcher.go實例快取、閒置回收、併發閘、暫存 profile 啟動Close、SetMaxConcurrency、Browser、DefaultUserAgent、ErrProfileNotFound
Cookie 解密core/cookie.go(macOS/Linux)、core/cookieOther.go(回傳錯誤的 stub;實務上走不到,其他平台在此之前就已退回一般瀏覽器)鑰匙圈取密碼、PBKDF2、AES-CBC 解密、組 CDP cookie無(內部)
內容處理core/markdown.go快照合併、時間元素內聯、Markdown 與樹狀輸出、去重Merge、HTMLToMarkdown、HTMLToNode、DedupTree、DedupMarkdownParagraphs、InlineTimeElements、Node

Chrome 透過 go-rod 以 Chrome DevTools Protocol 驅動。go-rod 與 chromedp 是需要逐步撰寫流程的 CDP 驅動程式;go-browser 把導覽、等待穩定、同意橫幅處理、捲動與轉換包成一次 Fetch 呼叫。
內容轉換方面,JohannesKaufmann/html-to-markdown 轉換你手上已有的 HTML;go-browser 先以 Chrome 渲染頁面、用 go-readability 擷取主要內容,再以自身基於 golang.org/x/net/html 的 HTMLToMarkdown 轉換。playwright-go 是控制 Chromium、Firefox、WebKit 的瀏覽器自動化函式庫,geziyor 是支援 JS 渲染的爬蟲框架;go-browser 只驅動 Chrome,每次 Fetch 回傳一個頁面。Anakin 是自架的網頁擷取 API 服務,回傳 Markdown 或 JSON;go-browser 則是直接匯入 Go 程式的函式庫。
注入頁面的三支腳本以 go:embed 內嵌於 core/embed/:stealth.js(反偵測)、listener.js(載入完成判定)、consent.js(同意橫幅)。

跨切原則


原則實作
Context 全程傳遞Fetch 的 ctx 傳到 settle、consent eval 與捲動等待;逾時由 timeout 參數包成子 context
併發由 semaphore 控制acquireSem 取得名額後才建立 page,load 結束即釋放
資源釋放成對launchWithSnapshot 回傳 cleanup 關閉瀏覽器並刪暫存目錄;快取實例由 evictor 或 Close 回收
降級不中斷找不到 Chrome 設定檔時回 ErrProfileNotFound,由 fetchWith 改走一般瀏覽器
失敗可辨識站點封鎖回 *Error{Status},萃取失敗回一般 error;兩者在路由層意義不同

延伸閱讀


模組級的完整展開(各模組流程圖、sequence、狀態機)在 repo 的 doc/architecture.zh.md。單一流程的細節請看 核心概念。
EN