oh-my-webbridge 使用手冊
Skip to Content

動作

指令端點、每個瀏覽器動作、選擇器語法與錯誤碼。

技術預覽

omw 目前是技術預覽版,正在快速迭代。之後的版本一定會有破壞相容性的變更。

每個瀏覽器動作都經由 daemon 的 POST /command,位址為 http://127.0.0.1:17373。請求帶有 omw connection 印出的 Bearer token。CLI 以 omw call 包裝它,SDK 以 call 包裝它(請見 CLI 與 SDK)。

請求

欄位型別意義
sessionstring工作階段名稱,由 1 到 96 個字元組成,可用字母(包括 CJK)、數字、_、. 或 -。必填。
actionstring下列表格中的動作名稱。必填。
argsobject動作引數。預設為 {}。
timeoutMsnumber期限,單位為毫秒,範圍 1 到 120000,預設 30000。它涵蓋排隊與執行。其他值(包括 0)會以 invalid_request 失敗。
browserstringchrome 或 firefox。省略時,依序使用已綁定到該工作階段的瀏覽器、唯一已連線的瀏覽器,或 Chrome。

本文是一個 JSON 物件,上限 2 MiB,不可含有未知欄位。名稱與既有綁定重複的工作階段,依 工作階段與分頁 的規則路由。

{
  "session": "research",
  "action": "navigate",
  "args": { "url": "https://example.com", "group_title": "Research" },
  "timeoutMs": 30000
}

請求本文也可以帶 id,這是一個字串,回覆會原樣帶回。省略時,daemon 會指派一個以小寫 36 進位表示的 Snowflake ID。成功的呼叫會回傳這個 id 與動作結果:

{
  "id": "uvwoyqsusjk",
  "result": { "success": true, "tabId": 412, "url": "https://example.com/" }
}

失敗的呼叫回傳 id 與錯誤,而不是結果,並帶有 錯誤 表格中的 HTTP 狀態碼:

{
  "id": "uvwoyqsusjk",
  "error": { "code": "stale_ref", "message": "element reference expired; take a fresh snapshot" }
}

頁面動作在工作階段目前的分頁中執行。傳入 tabId(或 tab),即可操作該工作階段持有的另一個分頁,而不必切換過去。

動作引數備註
navigateurl、newTab、group_title、預設集欄位除非工作階段已有目前分頁,或設定了 newTab,否則開啟一個背景任務分頁。URL 必須是 HTTP(S) 或 about:blank。
find_taburl(完整 URL 或主機名稱)、active為工作階段認領既有分頁。active: true 借用瀏覽器的使用中分頁。回傳 tabId、url、borrowed。
list_tabs無列出這個工作階段擁有或借用的分頁,含 tabId、url、title、active、borrowed、groupTitle。
switch_tabtabId讓該分頁成為目前分頁。已被丟棄的分頁會先重新載入;結果會回報 revived。
window_newurl、預設集欄位開啟獨立的視窗,認領其分頁,並回傳 tabId 與 windowId。
close_tabtabId關閉工作階段建立的分頁。借用的分頁不會被關閉。
close_session無關閉任務分頁、釋放借用的分頁,並移除瀏覽器綁定。回傳已關閉的分頁數量。
historycmd:list、back、forward、reloadlist 回傳導覽項目。每次 history 呼叫都會丟棄該分頁的參照與框架選擇。

一個工作階段最多持有 32 個分頁,任務分頁與借用的分頁合計。

讀取

動作引數備註
snapshotinteractive、maxDepth帶有 @e 參照的無障礙樹,另含 url、title、truncated。深度上限為 64。輸出在 4000 個節點或 192000 個字元時停止。
findquery、快照欄位對快照各行做不分大小寫的搜尋。最多 100 筆符合。
read_page無url、title,以及 document.body.innerText 的前 192000 個字元。
evaluatecode、contextId執行一個運算式,並回傳 { type: "value", value }。需要 await 時,使用非同步 IIFE。
getselector、property、attributetext、html、value、attr、count、box、styles、title、url。
isselector、propertyvisible、enabled、checked、editable。回傳布林值 value。
locateby、value、name、nth、cmd、text、property依 by(role、text、label、placeholder、alt、title、testid、css、xpath)建立選擇器,並執行 cmd,這是一個元素動作,預設為 get。
dialog_status無以 dialog 回傳待處理的 JavaScript 對話框,或回傳 null。

輸入

動作引數備註
click、dblclick、mouse_clickselector,或 x 與 y、button在元素中心送出滑鼠事件。
hoverselector把指標移到元素上。
fillselector、value取代 input、textarea 或 contenteditable 元素的內容。value 為空字串時會清空內容。
key_typetext、selector在已聚焦的元素插入文字,或先聚焦 selector。
send_keyskeys單一按鍵,或 Control+A、Meta+A 這類組合鍵。具名按鍵包括 Enter、Tab、Escape、Backspace、Delete、方向鍵、Home、End、PageUp、PageDown、Space。
keyboardcmd:down、up、insertText;key、text較低階的按鍵控制,用於按住修飾鍵。
mousecmd:move、down、up、wheel;x、y、button、amount原始的指標控制。
scrollselector,或 direction、amount、x、y指定選擇器時,把該元素捲動到中間。否則依 amount(0 到 100000,預設 600)朝 up、down、left 或 right 滾動滾輪。
select_optionselector、value以值或顯示文字比對選項,然後觸發 input 與 change。
dragfrom、to在 from 按下,分十個步驟移動,並在 to 放開。
focus、check、uncheckselectorcheck 與 uncheck 會先讀取目前狀態,並驗證結果;重複執行不會切換狀態。單選按鈕只支援 check。
dialogaccept、promptText回應待處理的對話框。accept 預設為 false。

等待

條件成立時,wait 立即回傳,否則每 75 ms 再檢查一次。到請求期限前 500 ms 條件仍未成立時,wait 以 wait_timeout 失敗。即使期限在 500 ms 以內,它也至少檢查一次。期限以 timeoutMs 設定,omw call 則用 --timeout-ms。設定以下其中一個欄位:

欄位意義
selector第一個符合的元素存在、有邊界框,且不是 visibility: hidden。
textdocument.body.innerText 包含該字串。
url目前的 URL 符合。* 可比對任意一段字元。
expressionJavaScript 運算式為真值。
loadload 等待 readyState === "complete";domcontentloaded 等待文件離開 loading 狀態。
statevisible(預設)或 hidden,後者會反轉條件。

框架

動作或引數意義
frame {"cmd": "list"}列出框架,含 id、name 與 url,包括跨行程的子框架。
frame {"selector": "iframe#panel"}選取包含符合之 iframe 元素的框架。
frame {"frameId": "..."}、frame {"name": "..."}、frame {"url": "..."}依 id、名稱或完整 URL 選取。
frame {"cmd": "main"}回到主框架,並丟棄該框架的參照。

選取框架後,頁面動作在該框架中執行。選取框架會丟棄先前的參照,並需要重新取得快照。

框架導覽或被移除時,選取就會結束;在 Chrome 中,分頁的偵錯工作階段結束時也會結束,例如使用者在 Chrome 的偵錯提示上按了取消,或擴充功能的 worker 重新啟動。之後第一個要在該框架執行的動作會以 frame_unavailable 失敗一次,再之後的動作使用主框架。

檔案與擷取

動作引數備註
screenshotformat(png、jpeg)、quality(0 到 100)、selector、fullPage、path回傳 path、sizeBytes 與 mimeType。沒有 path 時,檔案會放在 daemon 的成品目錄下。既有的路徑會被拒絕。
save_as_pdfpaper_format(預設 letter;另有 legal、a4、a3、tabloid)、landscape、scale(0.1 到 2)、print_background、path以分塊方式把 PDF 串流寫到磁碟,並回傳 path、sizeBytes、mimeType 與 pageTitle。僅限 Chrome。
uploadselector、files執行瀏覽器之機器上的絕對路徑。Chrome 需要在 chrome://extensions 為擴充功能開啟「允許存取檔案網址」。對 Firefox,daemon 會內嵌檔案內容:每個指令 16 MiB,進行中的合計 64 MiB。
downloadurl(HTTP(S))、filename在瀏覽器所在的主機上回傳 path、sizeBytes、mimeType 與 id。取消或逾時會中斷下載。

編碼後的結果超過 32 MiB 的螢幕截圖,會以 result_too_large 失敗。

網路、主控台、儲存空間與 cookie

動作引數備註
networkcmd:start、stop、list、detail;filter、requestId每個分頁保留最近 500 個請求。filter 是 URL 子字串。detail 回傳回應本文。在 Chrome 中,記錄範圍是 start 時所選的框架:主框架及其同行程的 iframe,或一個跨行程的 iframe。之後選取其他框架不會改變它。
consolecmd:start、list、clear、stop每個分頁最多儲存 200 筆項目,每筆截斷為 8192 個字元。
storagecmd:list、get、set、remove、clear;kind(local、session)、name、value只讀寫目前的來源。回傳 origin、kind,以及 value 或整個儲存空間。
cookiescmd:list、set、delete、clear;data、name範圍限於目前的 URL。set 把 data 直接傳給 cookie 欄位。

模擬

欄位意義
width、height視埠大小,單位為 CSS 像素,各為 1 到 16384。變更裝置度量時,兩者都必須提供。
deviceScaleFactor、mobile度量覆寫所用的裝置像素比與行動裝置旗標。
colorScheme供 prefers-color-scheme 使用的 dark 或 light。
latitude、longitude地理位置。兩者必須一起提供。
offline讓頁面離線或恢復連線。
data額外的 HTTP 標頭:最多 128 個字串值與 32 KiB,不可含有 CR 或 LF。

設定會在工作階段內持續有效,並在新分頁導覽之前套用到它們。Chrome 結束分頁的偵錯工作階段時(例如擴充功能的 worker 重新啟動後)會丟棄這些設定;工作階段的任務分頁收到下一個指令時會再次套用。借用的分頁不在其內。

批次

batch 接受 steps,這是由 { action, args } 物件組成的陣列,含 1 到 64 項。步驟在同一個請求中依序執行,並在第一個錯誤時停止。錯誤保留失敗步驟的錯誤碼,訊息以 batch step N of M (action): 開頭,表示第 1 到第 N-1 步已經完成。已完成的步驟不會還原。batch、close_session、screenshot、save_as_pdf、artifact_read 與 artifact_close 不能出現在批次內。

預設集

欄位意義
presetanti-ad(預設)、zen 或 none。
environment安裝內附的外觀規則與 scriptlet。從下一個文件起套用。
zenimages、fonts、css、javascript。true 會封鎖該資源類型。
cmdstatus 讀取該分頁的計數器、攔截與後備原因。

組態儲存在工作階段上,並套用到任務分頁。借用的分頁不在其內。navigate 接受相同的欄位,並在導覽開始後儲存它們。請見頁面預設集。

CDP

cdp 對分頁送出一個 Chrome DevTools Protocol 指令:method、params,以及子目標可選的 sessionId。它原封不動地回傳協定結果。

有兩個方法會改變橋接器自身的狀態。Runtime.disable 結束其工作階段的框架選擇;沒有 session id 的 Page.disable 使該分頁的 @e 參照失效;下一次快照或導覽會重新啟用這些事件。

daemon 在內部使用 cdp_attach、cdp_detach、artifact_read、artifact_close 與 list_targets。不要自行送出它們。

選擇器

每個接受 selector 的動作都接受下列形式。

形式範例比對方式
CSSbutton[type=submit]、css=.card a選擇器查詢。也會搜尋開啟的 shadow root。
@e 參照@e<generation>.<index>最新 snapshot 中的節點。
role=role=button[name="Submit"]無障礙角色,以及可選的名稱。名稱是 JSON 字串,須完全相符。
text=text=Sign in、text="Sign in"轉譯後的文字。未加引號的值比對不分大小寫的子字串;加引號的值須完全相符。
label=label=Email關聯的標籤文字或 aria-label。
placeholder=、alt=、title=placeholder=Search對應的屬性。
testid=testid=searchdata-testid 屬性。
xpath=xpath=//table//a只在目前文件中執行的 XPath。不會穿越 shadow root。

附加 >>nth=0 取第一個符合項,或附加 >>nth=-1 取最後一個。文字、CSS 與屬性定位器會穿越開啟的 shadow root。它們看不到封閉的 shadow root。

參照的存續期間

@e 參照屬於單一文件世代。每次快照都以新的世代為參照編號,世代是 36 進位的 Snowflake ID。在 Chrome 中,新的快照、框架選擇、新的主文件(導覽或重新載入),或分頁 URL 的變更,都會使它們失效。在所選框架內取得的快照,也會在該框架導覽、重新載入、被移除,或選取結束時過期。其他 iframe 載入或導覽,不影響它的有效性。在 Firefox 中,參照存在於產生它們的文件內;請見 Firefox。

錯誤

每個錯誤都帶有 code 與 message。HTTP 狀態碼列於下方;這裡未列出的錯誤碼回傳 502。

錯誤碼HTTP意義處理方式
invalid_request400本文被拒絕:有未知欄位、缺少 action 或 session、工作階段名稱含有不允許的字元、browser 無效,或 timeoutMs 超出 1 到 120000。修正 JSON。訊息會指出欄位。
invalid_args400引數缺少、型別錯誤,或超出範圍,包括無法解析的選擇器。screenshot 或 save_as_pdf 的路徑已經存在、它的目錄無法建立或寫入,或它所在的檔案系統無法建立硬連結時,也會被拒絕。閱讀訊息;它會指出動作與引數。
unsupported501目標瀏覽器沒有這個動作,或沒有它的某個引數。不要重試。改用其他動作,或使用 Chrome 工作階段。
busy429容量限制已滿:指令名額、每個工作階段 32 個分頁、每個瀏覽器 128 個工作階段、Firefox 上傳額度,或兩個同時進行的成品工作。也可能是工作階段在指令路由期間改到另一個瀏覽器。降低並行數量,並在先前的指令完成後重試。
browser_offline503目標瀏覽器沒有擴充功能連線,包括綁定到未連線瀏覽器的工作階段。檢查 omw doctor 與擴充功能,或在新的工作階段中繼續。
session_browser409工作階段綁定到另一個瀏覽器,而請求指定了這個瀏覽器。移除 browser,或關閉該工作階段並開始新的工作階段。
outcome_unknown504指令可能已經執行:期限、取消、傳輸寫入或斷線切斷了回覆,或指令執行期間頁面導覽或偵錯器中斷連線。訊息會指出原因。重複之前,先觀察頁面或網路狀態。切勿盲目重送提交、付款或發布操作。
wait_timeout408wait 的條件在期限前沒有成立。wait 不會變更頁面。以更長的期限再次送出 wait,或檢查條件。
tab_busy409該分頁屬於另一個工作階段。使用這個工作階段持有的分頁,或使用另一個工作階段。
stale_ref409@e 參照比它所屬的文件存活得更久。重新取得 snapshot。
no_tab502頁面動作在工作階段還沒有分頁時執行,或在目前分頁以 close_tab 以外的方式關閉之後執行。執行 navigate 或 find_tab,或傳入工作階段另一個分頁的 tabId。
tab_missing502find_tab 沒有符合的分頁,或指令指定的分頁已經關閉。先在這個工作階段中開啟該頁面,或傳入 active: true 借用瀏覽器的使用中分頁。分頁已關閉時,改在另一個分頁繼續。
restricted_tab502該分頁不是一般的、非無痕的 HTTP(S) 頁面。導覽到 HTTP(S) 頁面。瀏覽器內部頁面無法用指令碼操作。
borrowed_tab502動作需要工作階段建立的分頁:關閉它,或對借用的分頁套用預設集。用 navigate 開啟任務分頁。
element_missing502選擇器沒有符合任何元素。檢查選擇器,或重新取得快照。
element_hidden502元素沒有邊界框,因此沒有可點擊的中心。把它捲動到可見範圍,或等待它轉譯完成。
element_action_failed502頁面拒絕了這個操作,例如填寫不可編輯的元素,或選取不存在的選項。用 get 或 is 檢查,並調整動作。
state_mismatch502check 或 uncheck 讓控制項停在錯誤的狀態。用 is 重新讀取,然後重試,或改為點擊它。
evaluation_failed502evaluate 擲出例外,或內部頁面指令碼擲出例外。在 Firefox 中,也包括結果無法傳回的 evaluate,例如 DOM 節點、Window 或 BigInt;程式碼已經執行。修正運算式,或傳回一般資料。訊息帶有頁面例外。
frame_missing502frame 找不到符合所給選擇器、id、名稱或 URL 的框架。用 frame {"cmd":"list"} 列出框架,並選取其中一個。
frame_unavailable502所選的框架已被取代、移除或失去其執行環境,或分頁的偵錯工作階段已結束。之後的指令使用主框架;如果工作要在該框架繼續,請重新選取它。
history_missing502history back 或 forward 在該方向上沒有項目。先讀取 history {"cmd":"list"}。
request_missing502該請求沒有網路紀錄,或紀錄已被逐出。開始記錄,重現問題,然後讀取 list。
request_pending502回應本文尚未完整。等 list 中出現 complete: true,再重試 detail。
request_failed502請求本身失敗。讀取該項目上的錯誤文字。
body_unavailable502Firefox 沒有保留回應本文:WebSocket、被較新的本文擠出,或回應中斷。開著 network 記錄重新送出請求,或從頁面讀取資料。
download_missing502瀏覽器沒有列出該下載。重試 download。
download_failed502瀏覽器中斷了下載。閱讀訊息並重試。
file_access_required502Chrome 的 upload 需要擴充功能的「允許存取檔案網址」開關,而它預設為關閉。在 chrome://extensions 找到 oh-my-webbridge,開啟「允許存取檔案網址」後重試。
window_failed502新視窗沒有分頁。重試 window_new。
result_too_large502結果在傳輸時超過 32 MiB、儲存的螢幕截圖或 PDF 超過 100 MiB,或網路本文在 Chrome 中超過 2 Mi 個字元、在 Firefox 中超過 1 MiB。縮小結果:螢幕截圖使用 selector 或 jpeg,並讀取較小的片段。
debugger_unavailable502Chrome 拒絕附加偵錯工具,例如因為 DevTools 已開啟,或原則封鎖了它。關閉該分頁的 DevTools 並重試。
browser_error502擴充功能回報了沒有錯誤碼的錯誤。閱讀訊息,重試一次,然後回報。
internal502daemon 端的失敗,例如編碼請求時出錯。重試。如果持續發生,重新啟動 daemon。

貢獻者

頁面歷史