文件 v0.3.2

Fetch 路由

Fetch 如何在 headless 與有頭瀏覽器之間選擇,以及唯一會嘗試兩次的情況。

決策流程

graph TB
    A[Fetch] --> B{Option.Headless}
    B -->|true| C[headless,不重試]
    B -->|false| D{session domain 且有 GUI}
    D -->|是| E[headed,不重試]
    D -->|否| F[headless 首發]
    F --> G{403 / 429 / 503}
    G -->|否| H[回傳結果]
    G -->|是| I{有 GUI}
    I -->|否| H
    I -->|是| J[headed 重試一次]
分支 條件 嘗試次數
強制 headless Option.Headless 為 true 1 次,headless
Session 網域 主機在 session 清單內且有 GUI 1 次,有頭
預設 其他情況 先 headless,僅被擋時以有頭重試一次

什麼算被擋

只有三個狀態碼:403、429、503,來源可以是 *Error 也可以是 Result.Status。404、204、no article extracted 都不觸發重試——那些是頁面不存在或萃取失敗,換一種瀏覽器模式不會改變結果。非 *Error 的錯誤(啟動失敗、逾時)直接回傳,不重試。

just a moment 這類驗證頁標題會在此判斷前先轉成 403,Cloudflare 類型的中介頁因此能進入有頭重試。

Session 網域

headless 下鮮少能渲染出有效內容的社群網站,在有 GUI 時直接走有頭瀏覽器。清單內嵌於 core/embed/session_domains.json,主機等於清單項目或以 . 加項目結尾即命中:

facebook.com、fb.com、fb.watch、twitter.com、x.com、instagram.com、linkedin.com、threads.net、tiktok.com、pinterest.com、snapchat.com、weibo.com、weibo.cn、xiaohongshu.com、xhs.link、douyin.com、bilibili.com、zhihu.com、discord.com、telegram.org、t.me、vk.com、quora.com

沒有 GUI 時這些主機走預設分支。

GUI 判定

hasDisplay() 在 macOS 恆為真;Linux 上 DISPLAY 或 WAYLAND_DISPLAY 非空即為真。容器與無桌面的伺服器因此永遠不會嘗試啟動有頭瀏覽器。有頭視窗放在 -32000,-32000,位於螢幕外。

EN