稿實戰(zhàn):227次操作踩9坑,瀏覽器自動化發(fā)布文章全流程)
1. 項目緣起與整體設計思路1.1 為什么想讓 AI 自己去發(fā)稿事情的起因很簡單。我手上有一個持續(xù)在維護的技術(shù)內(nèi)容賬號日常需要在騰訊云開發(fā)者社區(qū)保持更新頻率。寫過技術(shù)博客的人都知道從選題、寫稿、排版、配圖到最終發(fā)布一篇文章的完整鏈路走下來純手工操作少說也要一兩個小時。如果遇到需要反復調(diào)整格式、上傳圖片、填寫標簽的情況時間成本還會進一步拉高。我當時的想法是既然 AI 已經(jīng)能幫我寫稿了那為什么不讓它把“發(fā)布”這一步也一起干掉換句話說我希望構(gòu)建一個端到端的自動化流程讓 AI 從拿到一篇成稿開始自己打開瀏覽器、登錄社區(qū)、進入編輯器、粘貼正文、上傳封面圖、填寫分類標簽最后點擊發(fā)布。整個過程不需要我盯著屏幕我只需要在最后確認一下結(jié)果就行。這個想法聽起來不算復雜但真正動手之后才發(fā)現(xiàn)里面涉及的坑遠比想象中多。最終這次實戰(zhàn)跑下來AI 一共執(zhí)行了227 次操作耗時4.3 小時踩了9 個比較典型的坑。我把整個過程完整復盤一遍希望能給同樣在做瀏覽器自動化、AI Agent 操作網(wǎng)頁的朋友一些參考。1.2 核心關(guān)鍵詞與涉及的技術(shù)點這次實戰(zhàn)涉及的核心技術(shù)點主要有這么幾個browser-skill這是我用來驅(qū)動瀏覽器操作的核心能力模塊負責把“點擊”“輸入”“滾動”“截圖”這些動作封裝成 AI 可以調(diào)用的技能。bsk這是 browser-skill 的簡稱在日志和調(diào)試過程中我大量使用這個縮寫來標記操作來源。tencent-cloud-community-publish這是本次任務的場景標識代表“在騰訊云開發(fā)者社區(qū)發(fā)布文章”這一具體流程。execCommand這是富文本編輯器里插入內(nèi)容時繞不開的一個老 API也是本次踩坑的重災區(qū)。upload文件上傳環(huán)節(jié)涉及封面圖、正文配圖的處理同樣是自動化里最容易出問題的地方。這幾個關(guān)鍵詞基本覆蓋了整條鏈路的核心難點。下面我會按照“整體設計—核心細節(jié)—實操過程—問題排查”的順序把每個環(huán)節(jié)拆開講清楚。1.3 整體方案選型與背后的考量在方案設計階段我其實面臨幾個選擇。第一個選擇是用純 API 方式發(fā)布還是用瀏覽器自動化方式發(fā)布理論上如果社區(qū)提供開放的發(fā)布接口直接調(diào) API 是最穩(wěn)的。但實際情況是很多內(nèi)容平臺的發(fā)布接口并不對外開放或者需要復雜的鑒權(quán)流程。所以我最終選擇了瀏覽器自動化這條路——讓 AI 像真人一樣操作頁面。這樣做的好處是通用性強不依賴平臺是否開放接口壞處是穩(wěn)定性受頁面結(jié)構(gòu)影響大任何一個 DOM 變化都可能導致流程失敗。第二個選擇是用現(xiàn)成的自動化框架還是自己封裝 browser-skill我最終選擇了自己封裝。原因是我需要讓 AI 能夠“理解”當前頁面狀態(tài)而不是機械地執(zhí)行固定腳本。比如當頁面加載慢的時候AI 應該知道等待當某個按鈕找不到的時候AI 應該嘗試滾動或者換一種定位方式。這種“帶判斷的操作”是普通腳本很難做到的必須把操作封裝成 skill讓 AI 在每一步都能做決策。第三個選擇是一次性跑完還是分階段執(zhí)行我最終選擇了分階段。因為整個流程太長如果一次性跑一旦中間出錯前面的操作就白費了。分階段執(zhí)行的好處是每個階段可以單獨驗證、單獨重試大大降低了整體失敗率。提示做瀏覽器自動化時不要一上來就追求“全自動一把過”。先把流程拆成若干可獨立驗證的階段每個階段跑通之后再串聯(lián)這是最省時間的做法。2. 核心細節(jié)解析與實操要點2.1 browser-skill 的能力邊界與設計原則browser-skill 本質(zhì)上是一層封裝它把瀏覽器里常見的操作抽象成 AI 可以調(diào)用的函數(shù)。我設計的 skill 主要包括這幾類導航類打開指定 URL、前進、后退、刷新。定位類根據(jù)文本、CSS 選擇器、XPath 找到頁面元素。交互類點擊、輸入文本、清空輸入框、選擇下拉項。文件類上傳文件到指定 input 元素。狀態(tài)類獲取頁面文本、獲取元素屬性、截圖、等待某個條件成立。設計這些 skill 的時候我遵循了一個原則每個 skill 只做一件事并且返回足夠的信息讓 AI 判斷下一步。比如“點擊”這個 skill不僅要執(zhí)行點擊還要返回點擊后頁面是否發(fā)生了變化、有沒有彈窗出現(xiàn)、當前 URL 是否改變。這樣 AI 才能根據(jù)返回結(jié)果決定是繼續(xù)還是重試。這里有個很容易被忽略的點skill 的返回值設計比 skill 本身更重要。如果返回值信息不足AI 就會“盲操作”出錯率會飆升。我在早期版本里就是因為點擊 skill 只返回了“成功/失敗”導致 AI 在頁面沒加載完的時候誤判為成功后面一連串操作全部錯位。2.2 富文本編輯器的 execCommand 陷阱騰訊云開發(fā)者社區(qū)的編輯器是富文本編輯器這類編輯器最大的特點是不是一個簡單的 textarea而是一個 contenteditable 的 div。往里面插入內(nèi)容最直接的方式就是用document.execCommand(insertText, false, text)。但 execCommand 有幾個非??拥牡胤降谝凰呀?jīng)被標記為廢棄。雖然目前主流瀏覽器還支持但行為在不同瀏覽器、不同版本之間可能有差異。我在測試的時候就發(fā)現(xiàn)同樣的代碼在某個版本里能正常插入換一個版本就插不進去。第二它對換行和特殊字符的處理很不穩(wěn)定。普通文本還好一旦遇到代碼塊、表格、有序列表這些結(jié)構(gòu)execCommand 經(jīng)常會把格式搞亂。我最初嘗試直接把整篇 Markdown 轉(zhuǎn)成 HTML 再插入結(jié)果編輯器把很多標簽都過濾掉了代碼塊直接變成了一坨純文本。第三它和編輯器的內(nèi)部狀態(tài)可能不同步。有些富文本編輯器會在內(nèi)部維護一份數(shù)據(jù)模型execCommand 直接操作 DOM 之后編輯器的數(shù)據(jù)模型并沒有更新導致你看著內(nèi)容進去了但一提交就發(fā)現(xiàn)內(nèi)容是空的。我最終的解決方案是分段插入 模擬真實輸入。具體來說就是把文章按段落拆開逐段調(diào)用 execCommand 插入每插入一段就觸發(fā)一次 input 事件讓編輯器同步狀態(tài)。對于代碼塊這種特殊結(jié)構(gòu)我改用模擬鍵盤輸入的方式一個字符一個字符地敲進去雖然慢但穩(wěn)定性高很多。注意execCommand 的廢棄狀態(tài)意味著它不是長久之計。如果平臺后續(xù)升級編輯器這套方案可能需要重寫。做自動化時要對這類“依賴廢棄 API”的環(huán)節(jié)保持警惕留好備選方案。2.3 文件上傳環(huán)節(jié)的 upload 處理文件上傳是另一個重災區(qū)。瀏覽器的文件上傳通常依賴input typefile元素但自動化工具沒法直接操作系統(tǒng)的文件選擇對話框。解決辦法是繞過對話框直接把文件路徑設置到 input 元素的 files 屬性上。具體做法是先找到頁面上隱藏的 file input然后用自動化工具提供的“設置文件”能力把本地文件路徑傳進去。這一步的關(guān)鍵是找到正確的 input 元素。很多網(wǎng)站會把 file input 隱藏起來用一個漂亮的按鈕代替你點擊按鈕的時候?qū)嶋H上是觸發(fā)了那個隱藏 input 的 click。我在實操中遇到的坑是頁面上有多個 file input分別對應封面圖、正文配圖、附件等不同用途。如果定位錯了就會出現(xiàn)“封面圖傳到了正文里”這種尷尬情況。解決辦法是通過 input 的 accept 屬性、name 屬性或者它所在的父容器來精確定位。另外上傳之后一定要等待上傳完成的信號。有些網(wǎng)站上傳是異步的你設置完文件之后圖片還在后臺上傳這時候如果直接點發(fā)布圖片就會丟失。我的做法是監(jiān)聽網(wǎng)絡請求或者輪詢檢查圖片的 src 是否已經(jīng)變成了真實的 CDN 地址。3. 實操過程與核心環(huán)節(jié)實現(xiàn)3.1 階段一登錄態(tài)與頁面準備整個流程的第一步是確保登錄態(tài)。我沒有讓 AI 去模擬輸入賬號密碼因為那樣涉及驗證碼、二次驗證等問題太不穩(wěn)定。我的做法是復用已有的瀏覽器用戶數(shù)據(jù)目錄也就是讓自動化瀏覽器加載一個已經(jīng)登錄過的 profile。這樣打開社區(qū)頁面時直接就是登錄狀態(tài)。這一步的實操要點是啟動瀏覽器時要指定userDataDir參數(shù)指向一個已經(jīng)手動登錄過的目錄。第一次使用前我會手動打開這個瀏覽器登錄一次之后自動化流程就能直接復用。頁面準備階段AI 需要做的是打開社區(qū)創(chuàng)作頁面等待編輯器加載完成。這里的判斷條件是“編輯器區(qū)域出現(xiàn)且可編輯”。我用的檢測方法是輪詢檢查 contenteditable 元素的 presence同時檢查頁面是否有 loading 遮罩。3.2 階段二正文內(nèi)容的插入正文插入是整個流程里最耗時、最容易出錯的部分。我最終采用的策略是“分塊處理”把文章按 Markdown 結(jié)構(gòu)拆分成塊標題塊、段落塊、代碼塊、圖片塊、列表塊。對每種塊類型采用不同的插入策略。每插入一塊就驗證一次內(nèi)容是否正確進入編輯器。普通段落用 execCommand 插入代碼塊用模擬輸入圖片塊先上傳再插入引用。這個過程中我記錄了一個關(guān)鍵數(shù)據(jù)平均每插入一個塊需要 3 到 5 次操作包括定位、插入、驗證。一篇文章大概有 40 到 50 個塊所以光正文插入就消耗了 150 次左右的操作。這里有個實操心得插入順序要從后往前或者從前往后但不要跳著插。因為富文本編輯器的光標位置很容易亂如果你跳著插光標可能跑到意想不到的地方導致內(nèi)容錯位。我一開始就是隨機插入結(jié)果文章結(jié)構(gòu)全亂了后來改成嚴格順序插入才穩(wěn)定下來。3.3 階段三封面圖與標簽填寫正文搞定之后接下來是封面圖和標簽。封面圖的上傳相對獨立找到對應的 file input設置文件等待上傳完成即可。標簽填寫則是在輸入框里輸入標簽文字然后從下拉建議里選中。標簽這一塊有個小坑有些標簽需要精確匹配才能選中。如果你輸入的標簽文字和平臺已有的標簽不完全一致可能創(chuàng)建出一個新標簽或者干脆選不上。我的做法是先把目標標簽文字輸入然后等待下拉列表出現(xiàn)再從列表里選擇完全匹配的項。3.4 階段四發(fā)布前的最終校驗在點擊發(fā)布之前我做了一次完整的校驗包括標題是否正確填入正文塊數(shù)量是否和預期一致代碼塊格式是否保留封面圖是否上傳成功標簽是否選中分類是否選擇這個校驗環(huán)節(jié)幫我避免了好幾次“帶病發(fā)布”。有一次就是封面圖實際上傳失敗了但頁面上顯示了一個占位圖如果不仔細檢查就會誤以為成功。校驗通過之后點擊發(fā)布按鈕等待跳轉(zhuǎn)到文章詳情頁確認文章 ID 和標題正確整個流程才算結(jié)束。4. 常見問題與排查技巧實錄4.1 九個坑的完整記錄這次實戰(zhàn)踩的 9 個坑我整理成了一張表方便大家對照排查序號問題現(xiàn)象根本原因解決方案1編輯器內(nèi)容插入后消失execCommand 未觸發(fā) input 事件編輯器狀態(tài)未同步每次插入后手動觸發(fā) input 事件2代碼塊格式丟失直接插入 HTML 被編輯器過濾改用模擬鍵盤逐字符輸入3封面圖傳到了正文file input 定位錯誤通過 accept 屬性和父容器精確定位4圖片上傳后立即發(fā)布導致丟失未等待異步上傳完成輪詢檢查圖片 src 是否為 CDN 地址5標簽選不上輸入文字與平臺標簽不完全匹配從下拉建議中精確選擇6頁面加載慢導致點擊無效未等待元素可交互增加顯式等待和可交互檢測7光標位置錯亂跳序插入內(nèi)容嚴格按順序插入8登錄態(tài)失效profile 過期定期手動刷新登錄態(tài)9發(fā)布按鈕點擊無反應存在未填必填項發(fā)布前做完整校驗4.2 排查思路的通用方法遇到問題的時候我總結(jié)了一套通用的排查思路第一步截圖。不管什么問題先截圖看當前頁面狀態(tài)。很多時候問題一眼就能看出來比如彈了個錯誤提示、頁面還在 loading、某個必填項是空的。第二步看日志。browser-skill 的每次操作我都會記錄日志包括操作類型、目標元素、執(zhí)行結(jié)果。通過日志能快速定位到是哪一步開始出錯的。第三步縮小范圍。如果整個流程失敗不要從頭重跑而是從失敗的那一步單獨重試。這樣可以快速驗證是偶發(fā)問題還是必現(xiàn)問題。第四步手動復現(xiàn)。如果自動化怎么都跑不通就手動操作一遍看看真人操作時頁面是什么反應。很多時候自動化失敗是因為它模擬的操作和真人操作有細微差別。提示做瀏覽器自動化日志和截圖是你的兩條命。沒有這兩樣排查問題基本靠猜。4.3 提升穩(wěn)定性的幾個實操技巧除了排查問題我還總結(jié)了一些提升穩(wěn)定性的技巧給每個操作加超時和重試。不要假設一次就能成功失敗后自動重試 2 到 3 次成功率會大幅提升。用文本定位代替 CSS 選擇器。CSS 選擇器容易因為頁面改版失效而按鈕上的文字相對穩(wěn)定。關(guān)鍵操作后加短暫等待。不要操作完立刻進行下一步給頁面一點反應時間。把長流程拆成短流程。每個短流程獨立驗證降低整體失敗率。這次 227 次操作、4.3 小時的實戰(zhàn)雖然踩了不少坑但最終跑通了整條鏈路。對我來說最大的收獲不是“AI 能發(fā)稿”這個結(jié)果而是摸清了瀏覽器自動化在真實內(nèi)容平臺上的能力邊界和穩(wěn)定性瓶頸。后續(xù)如果要做類似的事情這套經(jīng)驗可以直接復用少走很多彎路。