動作
指令端點、每個瀏覽器動作、選擇器語法與錯誤碼。
技術預覽
每個瀏覽器動作都經由 daemon 的 POST /command,位址為 http://127.0.0.1:17373。請求帶有 omw connection 印出的 Bearer token。CLI 以 omw call 包裝它,SDK 以 call 包裝它(請見 CLI 與 SDK)。
請求
| 欄位 | 型別 | 意義 |
|---|---|---|
session | string | 工作階段名稱,由 1 到 96 個字元組成,可用字母(包括 CJK)、數字、_、. 或 -。必填。 |
action | string | 下列表格中的動作名稱。必填。 |
args | object | 動作引數。預設為 {}。 |
timeoutMs | number | 期限,單位為毫秒,範圍 1 到 120000,預設 30000。它涵蓋排隊與執行。其他值(包括 0)會以 invalid_request 失敗。 |
browser | string | chrome 或 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),即可操作該工作階段持有的另一個分頁,而不必切換過去。
導覽與分頁
| 動作 | 引數 | 備註 |
|---|---|---|
navigate | url、newTab、group_title、預設集欄位 | 除非工作階段已有目前分頁,或設定了 newTab,否則開啓一個背景任務分頁。URL 必須是 HTTP(S) 或 about:blank。 |
find_tab | url(完整 URL 或主機名稱)、active | 為工作階段認領既有分頁。active: true 借用瀏覽器的使用中分頁。回傳 tabId、url、borrowed。 |
list_tabs | 無 | 列出這個工作階段擁有或借用的分頁,含 tabId、url、title、active、borrowed、groupTitle。 |
switch_tab | tabId | 讓該分頁成為目前分頁。已被丟棄的分頁會先重新載入;結果會回報 revived。 |
window_new | url、預設集欄位 | 開啓獨立的視窗,認領其分頁,並回傳 tabId 與 windowId。 |
close_tab | tabId | 關閉工作階段建立的分頁。借用的分頁不會被關閉。 |
close_session | 無 | 關閉任務分頁、釋放借用的分頁,並移除瀏覽器綁定。回傳已關閉的分頁數量。 |
history | cmd:list、back、forward、reload | list 回傳導覽項目。每次 history 呼叫都會丟棄該分頁的參照與框架選擇。 |
一個工作階段最多持有 32 個分頁,任務分頁與借用的分頁合計。
讀取
| 動作 | 引數 | 備註 |
|---|---|---|
snapshot | interactive、maxDepth | 帶有 @e 參照的無障礙樹,另含 url、title、truncated。深度上限為 64。輸出在 4000 個節點或 192000 個字元時停止。 |
find | query、快照欄位 | 對快照各行做不分大小寫的搜尋。最多 100 筆符合。 |
read_page | 無 | url、title,以及 document.body.innerText 的前 192000 個字元。 |
evaluate | code、contextId | 執行一個運算式,並回傳 { type: "value", value }。需要 await 時,使用非同步 IIFE。 |
get | selector、property、attribute | text、html、value、attr、count、box、styles、title、url。 |
is | selector、property | visible、enabled、checked、editable。回傳布林值 value。 |
locate | by、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_click | selector,或 x 與 y、button | 在元素中心送出滑鼠事件。 |
hover | selector | 把指標移到元素上。 |
fill | selector、value | 取代 input、textarea 或 contenteditable 元素的內容。value 為空字串時會清空內容。 |
key_type | text、selector | 在已聚焦的元素插入文字,或先聚焦 selector。 |
send_keys | keys | 單一按鍵,或 Control+A、Meta+A 這類組合鍵。具名按鍵包括 Enter、Tab、Escape、Backspace、Delete、方向鍵、Home、End、PageUp、PageDown、Space。 |
keyboard | cmd:down、up、insertText;key、text | 較低階的按鍵控制,用於按住修飾鍵。 |
mouse | cmd:move、down、up、wheel;x、y、button、amount | 原始的指標控制。 |
scroll | selector,或 direction、amount、x、y | 指定選擇器時,把該元素捲動到中間。否則依 amount(0 到 100000,預設 600)朝 up、down、left 或 right 滾動滾輪。 |
select_option | selector、value | 以值或顯示文字比對選項,然後觸發 input 與 change。 |
drag | from、to | 在 from 按下,分十個步驟移動,並在 to 放開。 |
focus、check、uncheck | selector | check 與 uncheck 會先讀取目前狀態,並驗證結果;重複執行不會切換狀態。單選按鈕只支援 check。 |
dialog | accept、promptText | 回應待處理的對話框。accept 預設為 false。 |
等待
條件成立時,wait 立即回傳,否則每 75 ms 再檢查一次。到請求期限前 500 ms 條件仍未成立時,wait 以 wait_timeout 失敗。即使期限在 500 ms 以內,它也至少檢查一次。期限以 timeoutMs 設定,omw call 則用 --timeout-ms。設定以下其中一個欄位:
| 欄位 | 意義 |
|---|---|
selector | 第一個符合的元素存在、有邊界框,且不是 visibility: hidden。 |
text | document.body.innerText 包含該字串。 |
url | 目前的 URL 符合。* 可比對任意一段字元。 |
expression | JavaScript 運算式為真值。 |
load | load 等待 readyState === "complete";domcontentloaded 等待文件離開 loading 狀態。 |
state | visible(預設)或 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 失敗一次,再之後的動作使用主框架。
檔案與擷取
| 動作 | 引數 | 備註 |
|---|---|---|
screenshot | format(png、jpeg)、quality(0 到 100)、selector、fullPage、path | 回傳 path、sizeBytes 與 mimeType。沒有 path 時,檔案會放在 daemon 的成品目錄下。既有的路徑會被拒絕。 |
save_as_pdf | paper_format(預設 letter;另有 legal、a4、a3、tabloid)、landscape、scale(0.1 到 2)、print_background、path | 以分塊方式把 PDF 串流寫到磁碟,並回傳 path、sizeBytes、mimeType 與 pageTitle。僅限 Chrome。 |
upload | selector、files | 執行瀏覽器之機器上的絕對路徑。Chrome 需要在 chrome://extensions 為擴充功能開啓「允許存取檔案網址」。對 Firefox,daemon 會內嵌檔案內容:每個指令 16 MiB,進行中的合計 64 MiB。 |
download | url(HTTP(S))、filename | 在瀏覽器所在的主機上回傳 path、sizeBytes、mimeType 與 id。取消或逾時會中斷下載。 |
編碼後的結果超過 32 MiB 的螢幕截圖,會以 result_too_large 失敗。
網路、主控台、儲存空間與 cookie
| 動作 | 引數 | 備註 |
|---|---|---|
network | cmd:start、stop、list、detail;filter、requestId | 每個分頁保留最近 500 個請求。filter 是 URL 子字串。detail 回傳回應本文。在 Chrome 中,記錄範圍是 start 時所選的框架:主框架及其同行程的 iframe,或一個跨行程的 iframe。之後選取其他框架不會改變它。 |
console | cmd:start、list、clear、stop | 每個分頁最多儲存 200 筆項目,每筆截斷為 8192 個字元。 |
storage | cmd:list、get、set、remove、clear;kind(local、session)、name、value | 只讀寫目前的來源。回傳 origin、kind,以及 value 或整個儲存空間。 |
cookies | cmd: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 不能出現在批次內。
預設集
| 欄位 | 意義 |
|---|---|
preset | anti-ad(預設)、zen 或 none。 |
environment | 安裝內附的外觀規則與 scriptlet。從下一個文件起套用。 |
zen | images、fonts、css、javascript。true 會封鎖該資源類型。 |
cmd | status 讀取該分頁的計數器、攔截與後備原因。 |
組態儲存在工作階段上,並套用到任務分頁。借用的分頁不在其內。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 的動作都接受下列形式。
| 形式 | 範例 | 比對方式 |
|---|---|---|
| CSS | button[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=search | data-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_request | 400 | 本文被拒絕:有未知欄位、缺少 action 或 session、工作階段名稱含有不允許的字元、browser 無效,或 timeoutMs 超出 1 到 120000。 | 修正 JSON。訊息會指出欄位。 |
invalid_args | 400 | 引數缺少、型別錯誤,或超出範圍,包括無法解析的選擇器。screenshot 或 save_as_pdf 的路徑已經存在、它的目錄無法建立或寫入,或它所在的檔案系統無法建立硬連結時,也會被拒絕。 | 閲讀訊息;它會指出動作與引數。 |
unsupported | 501 | 目標瀏覽器沒有這個動作,或沒有它的某個引數。 | 不要重試。改用其他動作,或使用 Chrome 工作階段。 |
busy | 429 | 容量限制已滿:指令名額、每個工作階段 32 個分頁、每個瀏覽器 128 個工作階段、Firefox 上傳額度,或兩個同時進行的成品工作。也可能是工作階段在指令路由期間改到另一個瀏覽器。 | 降低並行數量,並在先前的指令完成後重試。 |
browser_offline | 503 | 目標瀏覽器沒有擴充功能連線,包括綁定到未連線瀏覽器的工作階段。 | 檢查 omw doctor 與擴充功能,或在新的工作階段中繼續。 |
session_browser | 409 | 工作階段綁定到另一個瀏覽器,而請求指定了這個瀏覽器。 | 移除 browser,或關閉該工作階段並開始新的工作階段。 |
outcome_unknown | 504 | 指令可能已經執行:期限、取消、傳輸寫入或斷線切斷了回覆,或指令執行期間頁面導覽或偵錯器中斷連線。訊息會指出原因。 | 重複之前,先觀察頁面或網路狀態。切勿盲目重送提交、付款或發布操作。 |
wait_timeout | 408 | wait 的條件在期限前沒有成立。wait 不會變更頁面。 | 以更長的期限再次送出 wait,或檢查條件。 |
tab_busy | 409 | 該分頁屬於另一個工作階段。 | 使用這個工作階段持有的分頁,或使用另一個工作階段。 |
stale_ref | 409 | @e 參照比它所屬的文件存活得更久。 | 重新取得 snapshot。 |
no_tab | 502 | 頁面動作在工作階段還沒有分頁時執行,或在目前分頁以 close_tab 以外的方式關閉之後執行。 | 執行 navigate 或 find_tab,或傳入工作階段另一個分頁的 tabId。 |
tab_missing | 502 | find_tab 沒有符合的分頁,或指令指定的分頁已經關閉。 | 先在這個工作階段中開啓該頁面,或傳入 active: true 借用瀏覽器的使用中分頁。分頁已關閉時,改在另一個分頁繼續。 |
restricted_tab | 502 | 該分頁不是一般的、非無痕的 HTTP(S) 頁面。 | 導覽到 HTTP(S) 頁面。瀏覽器內部頁面無法用指令碼操作。 |
borrowed_tab | 502 | 動作需要工作階段建立的分頁:關閉它,或對借用的分頁套用預設集。 | 用 navigate 開啓任務分頁。 |
element_missing | 502 | 選擇器沒有符合任何元素。 | 檢查選擇器,或重新取得快照。 |
element_hidden | 502 | 元素沒有邊界框,因此沒有可點擊的中心。 | 把它捲動到可見範圍,或等待它轉譯完成。 |
element_action_failed | 502 | 頁面拒絕了這個操作,例如填寫不可編輯的元素,或選取不存在的選項。 | 用 get 或 is 檢查,並調整動作。 |
state_mismatch | 502 | check 或 uncheck 讓控制項停在錯誤的狀態。 | 用 is 重新讀取,然後重試,或改為點擊它。 |
evaluation_failed | 502 | evaluate 擲出例外,或內部頁面指令碼擲出例外。在 Firefox 中,也包括結果無法傳回的 evaluate,例如 DOM 節點、Window 或 BigInt;程式碼已經執行。 | 修正運算式,或傳回一般資料。訊息帶有頁面例外。 |
frame_missing | 502 | frame 找不到符合所給選擇器、id、名稱或 URL 的框架。 | 用 frame {"cmd":"list"} 列出框架,並選取其中一個。 |
frame_unavailable | 502 | 所選的框架已被取代、移除或失去其執行環境,或分頁的偵錯工作階段已結束。 | 之後的指令使用主框架;如果工作要在該框架繼續,請重新選取它。 |
history_missing | 502 | history back 或 forward 在該方向上沒有項目。 | 先讀取 history {"cmd":"list"}。 |
request_missing | 502 | 該請求沒有網路紀錄,或紀錄已被逐出。 | 開始記錄,重現問題,然後讀取 list。 |
request_pending | 502 | 回應本文尚未完整。 | 等 list 中出現 complete: true,再重試 detail。 |
request_failed | 502 | 請求本身失敗。 | 讀取該項目上的錯誤文字。 |
body_unavailable | 502 | Firefox 沒有保留回應本文:WebSocket、被較新的本文擠出,或回應中斷。 | 開着 network 記錄重新送出請求,或從頁面讀取資料。 |
download_missing | 502 | 瀏覽器沒有列出該下載。 | 重試 download。 |
download_failed | 502 | 瀏覽器中斷了下載。 | 閲讀訊息並重試。 |
file_access_required | 502 | Chrome 的 upload 需要擴充功能的「允許存取檔案網址」開關,而它預設為關閉。 | 在 chrome://extensions 找到 oh-my-webbridge,開啓「允許存取檔案網址」後重試。 |
window_failed | 502 | 新視窗沒有分頁。 | 重試 window_new。 |
result_too_large | 502 | 結果在傳輸時超過 32 MiB、儲存的螢幕截圖或 PDF 超過 100 MiB,或網路本文在 Chrome 中超過 2 Mi 個字元、在 Firefox 中超過 1 MiB。 | 縮小結果:螢幕截圖使用 selector 或 jpeg,並讀取較小的片段。 |
debugger_unavailable | 502 | Chrome 拒絕附加偵錯工具,例如因為 DevTools 已開啓,或原則封鎖了它。 | 關閉該分頁的 DevTools 並重試。 |
browser_error | 502 | 擴充功能回報了沒有錯誤碼的錯誤。 | 閲讀訊息,重試一次,然後回報。 |
internal | 502 | daemon 端的失敗,例如編碼請求時出錯。 | 重試。如果持續發生,重新啓動 daemon。 |