合飛書機(jī)器人,實(shí)現(xiàn)報(bào)表數(shù)據(jù)全自動(dòng)化推送)
影刀結(jié)合飛書實(shí)現(xiàn)報(bào)表數(shù)據(jù)全自動(dòng)化推送做運(yùn)營(yíng)和財(cái)務(wù)的朋友應(yīng)該都有這種體會(huì)每天或者每周固定時(shí)間得從后臺(tái)導(dǎo)出報(bào)表整理數(shù)據(jù)再手動(dòng)發(fā)給領(lǐng)導(dǎo)或者同事。操作本身不難但架不住天天重復(fù)偶爾忘了發(fā)還會(huì)被問(wèn)一句“今天報(bào)表呢”。時(shí)間久了這事就成了一種隱形消耗。我自己就經(jīng)歷過(guò)一段這種日子所以后來(lái)花了一個(gè)周末用影刀加上飛書機(jī)器人把整個(gè)流程做成了全自動(dòng)推送。到現(xiàn)在跑了幾個(gè)月基本不用再碰它每天到點(diǎn)數(shù)據(jù)自己發(fā)到群里省心太多了。這篇文章就把我的完整實(shí)現(xiàn)思路和實(shí)操過(guò)程寫出來(lái)包括影刀腳本怎么設(shè)計(jì)、飛書機(jī)器人怎么配置、消息怎么發(fā)才好看、定時(shí)觸發(fā)怎么設(shè)置還有我踩過(guò)的幾個(gè)坑。不管你是做運(yùn)營(yíng)、財(cái)務(wù)還是搞數(shù)據(jù)分析只要你有“定時(shí)從某個(gè)系統(tǒng)取數(shù)然后發(fā)到飛書群里”的需求這套方法都可以直接抄作業(yè)。先說(shuō)一下整體方案能做什么影刀RPA負(fù)責(zé)定時(shí)打開系統(tǒng)、抓取報(bào)表、清洗處理數(shù)據(jù)飛書機(jī)器人負(fù)責(zé)把處理后的結(jié)果以文本、富文本甚至表格文件的形式推送到指定群聊。整個(gè)過(guò)程不需要寫復(fù)雜的后端服務(wù)也不需要你有編程基礎(chǔ)影刀的圖形化流程設(shè)計(jì)加上幾個(gè)Webhook請(qǐng)求就能搞定。1. 整體方案為什么選影刀和飛書機(jī)器人而不是自己寫服務(wù)1.1 核心需求拆解拋開具體業(yè)務(wù)場(chǎng)景任何“報(bào)表自動(dòng)化推送”的需求本質(zhì)上都可以拆成三個(gè)環(huán)節(jié)取數(shù)從某個(gè)系統(tǒng)、后臺(tái)、網(wǎng)頁(yè)或者Excel文件里拿到原始數(shù)據(jù)。加工對(duì)原始數(shù)據(jù)做清洗、匯總、格式整理變成適合閱讀或進(jìn)一步處理的表格。推送把加工后的結(jié)果發(fā)送到指定的平臺(tái)這里是飛書和指定的人/群里。這三個(gè)環(huán)節(jié)說(shuō)起來(lái)簡(jiǎn)單但落到實(shí)際執(zhí)行上難點(diǎn)往往在細(xì)節(jié)。比如取數(shù)時(shí)目標(biāo)系統(tǒng)可能沒有開放API只能通過(guò)網(wǎng)頁(yè)登錄去查加工時(shí)數(shù)據(jù)可能散落在多個(gè)Sheet里還可能帶格式混亂的臟數(shù)據(jù)推送時(shí)還要考慮消息在飛書里閱讀起來(lái)是否直觀是發(fā)純文字、卡片還是直接把Excel文件丟群里。影刀在這個(gè)方案里扮演的角色是“搬運(yùn)工和加工廠”它擅長(zhǎng)模擬人的操作去訪問(wèn)系統(tǒng)、抓取數(shù)據(jù)也能調(diào)用代碼塊做數(shù)據(jù)處理。飛書機(jī)器人則負(fù)責(zé)最后一公里的觸達(dá)它通過(guò)Webhook地址接收影刀發(fā)送的HTTP請(qǐng)求把消息轉(zhuǎn)成群聊里的內(nèi)容。1.2 為什么用RPA加Webhook而不是自己寫后端服務(wù)我最早其實(shí)想過(guò)直接寫一個(gè)Python腳本掛服務(wù)器上定時(shí)跑任務(wù)調(diào)用飛書接口推送。但這個(gè)方案在真實(shí)場(chǎng)景里有幾個(gè)繞不開的問(wèn)題目標(biāo)系統(tǒng)沒有API。很多內(nèi)部運(yùn)營(yíng)后臺(tái)、第三方平臺(tái)根本沒有對(duì)外開放的數(shù)據(jù)接口或者申請(qǐng)權(quán)限流程漫長(zhǎng)。RPA直接繞過(guò)了這個(gè)問(wèn)題模擬瀏覽器操作就行。服務(wù)器要錢要維護(hù)。公網(wǎng)服務(wù)器、定時(shí)任務(wù)、運(yùn)行日志這些都要自己折騰。影刀本身有客戶端還有調(diào)度功能裝在一臺(tái)常開電腦上就能跑成本低得多。排查問(wèn)題是需要可視化。寫服務(wù)跑掛了你要看日志、查代碼。影刀的流程運(yùn)行記錄非常直觀哪一步出錯(cuò)、卡在哪個(gè)元素上界面上看得一清二楚對(duì)非純技術(shù)背景的人來(lái)說(shuō)友好太多了。當(dāng)然Webhook推送這條路也有限制比如飛書自定義機(jī)器人對(duì)消息頻率有管控但正常發(fā)報(bào)表完全夠用。我的原則是能用簡(jiǎn)單方案解決的就不要引入重架構(gòu)。2. 影刀側(cè)報(bào)表數(shù)據(jù)抓取與預(yù)處理的完整流程2.1 數(shù)據(jù)獲取的兩種方式影刀操作數(shù)據(jù)的方式主要有兩類一類是通過(guò)界面自動(dòng)化去“看”頁(yè)面上的數(shù)據(jù)另一類是直接讀寫Excel文件。我在實(shí)際項(xiàng)目里這兩種都會(huì)用具體根據(jù)目標(biāo)系統(tǒng)的形態(tài)來(lái)定。如果數(shù)據(jù)源是網(wǎng)頁(yè)后臺(tái)比如運(yùn)營(yíng)數(shù)據(jù)平臺(tái)、ERP系統(tǒng)那影刀的標(biāo)準(zhǔn)流程就是啟動(dòng)瀏覽器 → 輸入賬號(hào)密碼登錄 → 點(diǎn)擊菜單進(jìn)入報(bào)表頁(yè)面 → 選擇篩選條件 → 點(diǎn)擊查詢 → 等待頁(yè)面加載 → 抓取表格數(shù)據(jù)。這里有幾個(gè)關(guān)鍵細(xì)節(jié)登錄時(shí)的驗(yàn)證碼能免則免。如果系統(tǒng)有驗(yàn)證碼建議提前在系統(tǒng)層面申請(qǐng)免驗(yàn)證碼登錄或者用影刀的 OCR 組件去識(shí)別。我自己的項(xiàng)目里目標(biāo)系統(tǒng)可以記住登錄態(tài)所以影刀直接復(fù)用瀏覽器的Cookie省掉了每次登錄的麻煩。抓取表格數(shù)據(jù)優(yōu)先使用影刀內(nèi)置的“獲取網(wǎng)頁(yè)表格數(shù)據(jù)”指令而不是去逐個(gè)讀取單元格。前者一次性能把整個(gè)表格的二維數(shù)組抓出來(lái)后者不僅慢而且容易受到頁(yè)面滾動(dòng)影響導(dǎo)致漏數(shù)據(jù)。等待頁(yè)面加載時(shí)別用固定延時(shí)去賭。影刀有“等待元素出現(xiàn)”這類指令用輪詢等待代替sleep穩(wěn)定性會(huì)好很多。我見過(guò)很多人寫腳本頁(yè)面還沒加載完就開始抓數(shù)據(jù)結(jié)果抓到一堆空值。如果數(shù)據(jù)源本身就是Excel文件那就更簡(jiǎn)單了。影刀可以直接讀取指定路徑下的Excel也可以通過(guò)文件對(duì)話框去操作。這里我建議提前約定好源文件的固定命名規(guī)則比如“銷售數(shù)據(jù)_20250601.xlsx”這樣影刀可以通過(guò)遍歷文件夾自動(dòng)找到最新的那個(gè)文件來(lái)讀。2.2 數(shù)據(jù)清洗和匯總處理報(bào)表數(shù)據(jù)很少是拿來(lái)就能直接發(fā)的通常涉及一些加工步驟。影刀本身支持單元格操作、列運(yùn)算但說(shuō)實(shí)話處理稍微復(fù)雜一點(diǎn)的邏輯用圖形化指令會(huì)顯得很笨拙。我更推薦的方式是在影刀流程中嵌入Python代碼塊用pandas來(lái)處理數(shù)據(jù)。實(shí)際項(xiàng)目中DataSource是一個(gè)匯總了多個(gè)分表的數(shù)據(jù)源。按日期維度匯總后需要計(jì)算同比環(huán)比還要把數(shù)值格式化成帶逗號(hào)和單位的字符串。這些如果用影刀自身的Excel指令逐個(gè)單元格算流程會(huì)非常臃腫。改用Python腳本之后十幾行代碼就能解決而且后續(xù)維護(hù)邏輯也更清晰。import pandas as pd df pd.read_excel(源數(shù)據(jù)路徑.xlsx) df[銷售額] df[銷售額].fillna(0) summary df.groupby(日期)[銷售額].sum().reset_index() summary[環(huán)比] summary[銷售額].pct_change().fillna(0) summary[銷售額顯示] summary[銷售額].apply(lambda x: f{x:,.0f} 元) summary.to_excel(待推送數(shù)據(jù).xlsx, indexFalse)注意事項(xiàng)是影刀嵌入Python時(shí)需要保證運(yùn)行環(huán)境里有pandas和openpyxl這兩個(gè)庫(kù)。一般影刀自帶的Python環(huán)境可能沒裝可以先在擴(kuò)展組件里確認(rèn)一下缺什么補(bǔ)什么。這一步很多人會(huì)忽略報(bào)錯(cuò)之后才回頭裝環(huán)境。2.3 報(bào)表文件的命名和歸檔數(shù)據(jù)加工完之后建議做兩個(gè)動(dòng)作一是把待推送的文件生成到一個(gè)單獨(dú)的輸出目錄文件名帶上日期方便留檔二是把原始文件移動(dòng)到“已處理”文件夾避免下次重復(fù)讀取。這里有個(gè)小經(jīng)驗(yàn)影刀在處理完數(shù)據(jù)后可以順手把輸出文件的最后修改時(shí)間記錄下來(lái)寫到日志或者飛書消息里。這樣如果推送過(guò)程中出了問(wèn)題回查的時(shí)候能快速確認(rèn)“數(shù)據(jù)到底是不是最新的”。輸出目錄結(jié)構(gòu)示例 D:\ReportAuto\ - 源數(shù)據(jù)\人工放置或系統(tǒng)導(dǎo)出 - 已處理\影刀處理完成后歸檔 - 待推送\影刀生成的最新報(bào)表 - 日志\運(yùn)行記錄與錯(cuò)誤快照3. 飛書機(jī)器人配置從創(chuàng)建到發(fā)送自定義消息3.1 創(chuàng)建一個(gè)群聊機(jī)器人飛書自定義機(jī)器人是目前最輕量的一種接入方式。不需要申請(qǐng)應(yīng)用不需要審核只要在飛書群里添加一個(gè)自定義機(jī)器人拿到Webhook地址就能通過(guò)HTTP請(qǐng)求往群里發(fā)消息。添加路徑我記得很清楚是在飛書群里打開“設(shè)置” → “群機(jī)器人” → “添加機(jī)器人” → 選擇“自定義機(jī)器人”。添加后飛書會(huì)給一個(gè)Webhook地址形如https://open.feishu.cn/open-apis/bot/v2/hook/xxxx-xxxx-xxxx這個(gè)地址要妥善保管因?yàn)槿魏文玫皆摰刂返娜硕寄芡豪锇l(fā)消息。飛書官方也支持設(shè)置簽名校驗(yàn)我建議從一開始就加上具體步驟是添加機(jī)器人時(shí)開啟“簽名校驗(yàn)”會(huì)生成一個(gè)密鑰后續(xù)在影刀發(fā)送請(qǐng)求時(shí)需要在請(qǐng)求頭里帶上用時(shí)間戳和密鑰生成的簽名值。后面我會(huì)給出Python代碼示例。3.2 文本消息和富文本消息的發(fā)送邏輯拿到Webhook地址之后發(fā)送消息的本質(zhì)就是對(duì)Webhook發(fā)一個(gè)POST請(qǐng)求請(qǐng)求體是JSON。最基本的文本消息格式import requests import json webhook 你的webhook地址 headers {Content-Type: application/json} payload { msg_type: text, content: { text: 今日銷售報(bào)表已生成請(qǐng)查收。 } } resp requests.post(webhook, headersheaders, datajson.dumps(payload)) print(resp.status_code, resp.text)如果是開了簽名校驗(yàn)的機(jī)器人還需要再加一步簽名計(jì)算。簽名的算法是把時(shí)間戳秒級(jí)和密鑰拼成字符串再用HMAC-SHA256加密最后把時(shí)間戳和簽名字符串放進(jìn)請(qǐng)求頭。import time import hmac import hashlib import base64 timestamp str(int(time.time())) secret 你的密鑰 string_to_sign f{timestamp}\n{secret}.encode(utf-8) hmac_code hmac.new(string_to_sign, digestmodhashlib.sha256).digest() sign base64.b64encode(hmac_code).decode(utf-8) headers { Content-Type: application/json, X-Lark-Signature: sign, X-Lark-Request-Timestamp: timestamp }富文本消息比純文本好看得多適合展示報(bào)表指標(biāo)。它的msg_type是“post”content里是一個(gè)二維數(shù)組也就是多個(gè)行每行里可以放多個(gè)文本段。我經(jīng)常用來(lái)發(fā)日?qǐng)?bào)第一行是標(biāo)題第二行是核心指標(biāo)第三、四行分別是環(huán)比和說(shuō)明。payload { msg_type: post, content: { post: { zh-CN: { title: 6月1日銷售數(shù)據(jù)日?qǐng)?bào), content: [ [{tag: text, text: 銷售額1,234,567 元, style: bold}], [{tag: text, text: 環(huán)比昨日12.5%}], [{tag: text, text: 備注華東區(qū)域增長(zhǎng)明顯。}] ] } } } }這里有個(gè)小技巧富文本消息里的文本段加上style: bold可以讓重要指標(biāo)加粗顯示閱讀體驗(yàn)提升非常大。大家在推送給領(lǐng)導(dǎo)看的時(shí)候務(wù)必把關(guān)鍵數(shù)字標(biāo)粗否則一串平鋪直敘的文字重點(diǎn)很難被注意到。3.3 把表格文件推送到群聊如果只是發(fā)文字摘要那數(shù)據(jù)明細(xì)怎么辦兩個(gè)思路一是把明細(xì)也貼進(jìn)消息里但飛書對(duì)消息內(nèi)容長(zhǎng)度有限制超出會(huì)被截?cái)喽侵苯影袳xcel文件發(fā)到群里這也是很多團(tuán)隊(duì)的實(shí)際需求。飛書機(jī)器人發(fā)送文件需要通過(guò)兩個(gè)步驟先把文件上傳到飛書拿到media_id再調(diào)用消息接口把media_id作為文件消息發(fā)出去。這里要注意的是上傳文件接口需要tenant_access_token而這又涉及創(chuàng)建一個(gè)飛書應(yīng)用。聽起來(lái)繞但其實(shí)成本也不高在飛書開放平臺(tái)創(chuàng)建一個(gè)企業(yè)自建應(yīng)用名字隨意。給應(yīng)用添加“上傳文件”和“發(fā)送消息”權(quán)限。拿到App ID和App Secret通過(guò)接口換取tenant_access_token。用token去上傳文件并發(fā)送。影刀里實(shí)現(xiàn)的時(shí)候我是在Python代碼塊里寫完整的請(qǐng)求邏輯import requests import json def get_tenant_token(app_id, app_secret): url https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal payload {app_id: app_id, app_secret: app_secret} resp requests.post(url, jsonpayload) return resp.json()[tenant_access_token] def upload_file(token, file_path): url https://open.feishu.cn/open-apis/im/v1/files headers {Authorization: fBearer {token}} with open(file_path, rb) as f: files {file: f} data {file_type: xlsx, file_name: file_path.split(/)[-1]} resp requests.post(url, headersheaders, datadata, filesfiles) return resp.json()[data][file_key] def send_file_message(token, chat_id, file_key): url https://open.feishu.cn/open-apis/im/v1/messages?receive_id_typechat_id headers {Authorization: fBearer {token}, Content-Type: application/json} payload { receive_id: chat_id, msg_type: file, content: json.dumps({file_key: file_key}) } resp requests.post(url, headersheaders, jsonpayload) return resp.json()這個(gè)流程有個(gè)細(xì)節(jié)chat_id不是你群里看到的ID需要調(diào)用“獲取群信息”接口來(lái)查。我當(dāng)時(shí)查這個(gè)參數(shù)費(fèi)了點(diǎn)時(shí)間建議在配置階段先寫一個(gè)小腳本把指定群的chat_id打印出來(lái)免得每次從日志里翻。實(shí)際上日常使用中我更推薦的替代方案是把Excel文件上傳到飛書云文檔上傳后直接變成飛書表格然后往群里發(fā)一個(gè)鏈接。這樣成員在線預(yù)覽不用下載文件也省去了chat_id查詢和復(fù)雜權(quán)限配置。具體實(shí)現(xiàn)可以用飛書開放平臺(tái)的導(dǎo)入云文檔接口影刀通過(guò)Webhook發(fā)鏈接消息即可。4. 定時(shí)觸發(fā)與穩(wěn)定性保障讓腳本在無(wú)人值守下更可靠4.1 影刀的定時(shí)觸發(fā)策略影刀RPA提供了多種觸發(fā)方式在流程的“設(shè)置”里可以配置定時(shí)觸發(fā)。支持按固定間隔比如每5分鐘、按固定時(shí)間點(diǎn)比如每天9點(diǎn)、按周/月周期等模式。對(duì)于報(bào)表推送場(chǎng)景我優(yōu)先用“固定時(shí)間點(diǎn)”精確到時(shí)分秒。我這里用的是三套觸發(fā)策略的組合第一套每天9點(diǎn)整觸發(fā)主流程執(zhí)行“登錄系統(tǒng) → 抓取日?qǐng)?bào)數(shù)據(jù) → 處理匯總 → 推送到飛書群”。第二套每天9點(diǎn)5分再觸發(fā)一次兜底檢查流程查詢飛書群里是否已經(jīng)有今天的報(bào)表消息。如果沒查到就重新執(zhí)行一次主流程。第三套每個(gè)周一9點(diǎn)額外執(zhí)行周報(bào)匯總流程生成周維度的報(bào)表數(shù)據(jù)并推送。第二套兜底策略是我后來(lái)加的。因?yàn)樽詣?dòng)化跑得再穩(wěn)也架不住網(wǎng)絡(luò)抖動(dòng)、系統(tǒng)維護(hù)、頁(yè)面改版這些不可控因素。定時(shí)復(fù)查一次相當(dāng)于給自己的自動(dòng)化上了個(gè)保險(xiǎn)。4.2 影刀斷點(diǎn)續(xù)跑與會(huì)話保持RPA腳本在長(zhǎng)時(shí)間無(wú)人值守情況下最怕的是運(yùn)行過(guò)程中彈出意外窗口、會(huì)話超時(shí)、或者電腦鎖屏導(dǎo)致頁(yè)面卡死。針對(duì)這些情況我有幾個(gè)實(shí)操建議關(guān)閉系統(tǒng)休眠和屏幕自動(dòng)鎖定。定時(shí)任務(wù)跑著跑著如果電腦休眠了影刀流程直接中斷。在運(yùn)行機(jī)器上把電源計(jì)劃設(shè)為“始終開啟”鎖屏也關(guān)掉。影刀設(shè)置里開啟“斷點(diǎn)續(xù)跑”或“異常重試”。當(dāng)某個(gè)步驟失敗時(shí)可以指定重試次數(shù)和重試間隔。我一般設(shè)為失敗后等60秒重試一次最多重試3次。關(guān)鍵步驟寫日志。影刀流程中的每一個(gè)核心節(jié)點(diǎn)我都通過(guò)“記錄日志”指令輸出一條運(yùn)行日志包含時(shí)間、步驟名、數(shù)據(jù)量。這樣即使沒趕上運(yùn)行過(guò)程回看日志也能準(zhǔn)確定位是哪一步出的問(wèn)題。關(guān)于鎖屏這個(gè)問(wèn)題我再多說(shuō)一句。如果公司電腦策略不允許關(guān)鎖屏還有一種方法是讓影刀在鎖屏狀態(tài)下仍然可以運(yùn)行但前提是瀏覽器頁(yè)面已經(jīng)預(yù)先打開且Cookie不過(guò)期。實(shí)操下來(lái)我建議在流程最開始加一個(gè)“解鎖屏幕”步驟如果檢測(cè)到鎖屏就自動(dòng)解鎖代碼塊里可以用Windows API發(fā)送解鎖命令。不過(guò)這塊各公司環(huán)境差異大建議先在自己電腦上把前兩種方法做好。4.3 飛書消息頻率限制與重試機(jī)制飛書自定義機(jī)器人對(duì)單條Webhook的發(fā)送頻率有一定限制正常情況下發(fā)報(bào)表根本不會(huì)觸發(fā)但當(dāng)消息內(nèi)容很長(zhǎng)、或者同一時(shí)間并發(fā)多條消息時(shí)還是可能收到“請(qǐng)求過(guò)于頻繁”的返回碼一般是19021。我在影刀流程里給所有發(fā)送請(qǐng)求都加了重試機(jī)制當(dāng)響應(yīng)碼為19021時(shí)等待10秒后重新發(fā)送最多重試5次。這個(gè)處理邏輯放在Python代碼塊里實(shí)現(xiàn)非常方便。def send_with_retry(payload, max_retry5): for i in range(max_retry): resp requests.post(webhook, headersheaders, jsonpayload) data resp.json() if data.get(code) 0: return True if data.get(code) 19021: time.sleep(10) continue else: print(f發(fā)送失敗: {data}) return False return False另外一個(gè)容易踩的坑是發(fā)送消息時(shí)payload里如果有非ASCII字符比如中文字段名一定要用json.dumps指定ensure_asciiFalse否則飛書端顯示出來(lái)的中文會(huì)變成\uXXXX亂碼。這個(gè)細(xì)節(jié)很隱蔽我之前排查了好久才定位到。5. 常見問(wèn)題與排查技巧我踩過(guò)的那些坑5.1 影刀側(cè)遇到的典型問(wèn)題影刀運(yùn)行時(shí)報(bào)錯(cuò)大多數(shù)集中在元素找不到、頁(yè)面加載慢、數(shù)據(jù)抓取為空這三類。我列一個(gè)速查表方便大家遇到問(wèn)題時(shí)直接對(duì)照排查。表格問(wèn)題現(xiàn)象可能原因排查方向元素找不到頁(yè)面改版選擇器失效更新元素選擇器改用圖片識(shí)別定位頁(yè)面加載慢導(dǎo)致抓取空數(shù)據(jù)固定延時(shí)不足改用“等待元素出現(xiàn)”指令輪詢登錄態(tài)失效Cookie過(guò)期或?yàn)g覽器緩存被清理流程增加重新登錄步驟抓取數(shù)據(jù)量比預(yù)期少頁(yè)面滾動(dòng)未到底部懶加載未觸發(fā)在抓取前執(zhí)行滾動(dòng)到底部操作Excel讀取報(bào)錯(cuò)文件被其他進(jìn)程占用先復(fù)制文件到臨時(shí)目錄再讀取其中“元素找不到”是最高頻的問(wèn)題。我建議在編寫影刀流程時(shí)凡是涉及點(diǎn)擊和抓取的頁(yè)面元素不要用絕對(duì)坐標(biāo)定位優(yōu)先使用文本選擇器或CSS選擇器。這樣后面系統(tǒng)頁(yè)面微調(diào)時(shí)腳本還能兼容。5.2 飛書側(cè)經(jīng)常遇到的問(wèn)題飛書消息發(fā)送失敗返回碼是最直接的排查依據(jù)。除了前面提到的19021頻率限制還有幾個(gè)常見返回碼表格返回碼含義處理方法19001簽名校驗(yàn)失敗參數(shù)錯(cuò)誤檢查時(shí)間戳和簽名算法確認(rèn)請(qǐng)求頭字段名正確19002機(jī)器人已停用在群設(shè)置里重新啟用機(jī)器人19003消息內(nèi)容為空或格式錯(cuò)誤檢查JSON結(jié)構(gòu)特別是content字段19004群不存在或機(jī)器人不在群內(nèi)確認(rèn)Webhook是否來(lái)源于目標(biāo)群19020消息推送太頻繁降低發(fā)送頻率或改為合并發(fā)送我碰到過(guò)一次印象很深的坑同一個(gè)Webhook地址在公司的辦公網(wǎng)絡(luò)環(huán)境下發(fā)送成功換到家里網(wǎng)絡(luò)就報(bào)簽名錯(cuò)誤。排查半天結(jié)果是因?yàn)橛暗兜腜ython環(huán)境里requests庫(kù)版本和公司環(huán)境不一致導(dǎo)致請(qǐng)求頭的編碼格式有差異。最后我把請(qǐng)求頭手動(dòng)指定為Content-Type: application/json; charsetutf-8問(wèn)題就消失了。建議大家在發(fā)送請(qǐng)求時(shí)都顯式加上charsetutf-8避免編碼差異。5.3 端到端的調(diào)試技巧調(diào)試整個(gè)流程時(shí)最忌諱的是等到定時(shí)觸發(fā)才發(fā)現(xiàn)問(wèn)題。我的習(xí)慣是寫完之后先手動(dòng)觸發(fā)一次完整流程并把影刀執(zhí)行過(guò)程中的截圖打開觀察每一步的實(shí)際運(yùn)行情況。重點(diǎn)觀察三個(gè)節(jié)點(diǎn)登錄環(huán)節(jié)是否穩(wěn)定通過(guò)數(shù)據(jù)抓取環(huán)節(jié)是否拿全了數(shù)據(jù)飛書消息是否在群里正常顯示如果這三步都OK再把定時(shí)觸發(fā)打開觀察兩三天。前兩天每天到點(diǎn)后主動(dòng)看一眼群消息確認(rèn)無(wú)誤后再?gòu)氐追攀?。調(diào)試過(guò)程中還有一個(gè)實(shí)用技巧影刀可以單獨(dú)運(yùn)行流程中的某一個(gè)子流程塊。這樣修復(fù)問(wèn)題時(shí)不需要每次都從頭把整個(gè)流程跑一遍。比如我只是改了數(shù)據(jù)清洗邏輯就單獨(dú)運(yùn)行處理數(shù)據(jù)那個(gè)子流程效率會(huì)高很多。6. 進(jìn)階擴(kuò)展讓自動(dòng)化方案更接近真正的“全自動(dòng)”6.1 飛書多維表格作為數(shù)據(jù)落地終端如果你覺得“每天推一條報(bào)表到群里”還不夠想讓數(shù)據(jù)自動(dòng)匯總到一個(gè)表格里不占群消息還能持久化那飛書多維表格是一個(gè)很好的落地終端。多維表格本身就是一個(gè)輕量數(shù)據(jù)庫(kù)支持API寫入。影刀在抓取完數(shù)據(jù)后可以通過(guò)飛書開放API把數(shù)據(jù)一行行插入到多維表格中。這樣每天的數(shù)據(jù)都在同一個(gè)表里不斷追加月底直接看圖表趨勢(shì)連二次匯總都省了。實(shí)現(xiàn)思路并不復(fù)雜先在飛書多維表格里建好字段然后通過(guò)影刀Python代碼塊調(diào)用飛書多維表格API按行插入數(shù)據(jù)。關(guān)鍵是API的鑒權(quán)方式和發(fā)消息不同需要獲取應(yīng)用憑證用tenant_access_token去請(qǐng)求。這是我的延伸擴(kuò)展方向目前已經(jīng)在部分項(xiàng)目中應(yīng)用日常跑批效果很好。6.2 飛書H5免登錄和網(wǎng)頁(yè)自動(dòng)化結(jié)合熱搜詞里出現(xiàn)了“vue 飛書h5免登錄授權(quán)”這其實(shí)是另一個(gè)場(chǎng)景通過(guò)飛書賬號(hào)體系免登錄訪問(wèn)Web應(yīng)用。如果公司內(nèi)部的報(bào)表系統(tǒng)支持飛書免登那么影刀登錄環(huán)節(jié)會(huì)進(jìn)一步簡(jiǎn)化。原理是飛書開放平臺(tái)提供免登授權(quán)服務(wù)Web應(yīng)用前端通過(guò)JavaScript SDK獲取授權(quán)碼后端再換取用戶身份。影刀在啟動(dòng)瀏覽器之后可以跳轉(zhuǎn)到免登鏈接自動(dòng)完成授權(quán)然后進(jìn)入報(bào)表頁(yè)面抓數(shù)。這樣就不用維護(hù)獨(dú)立的賬號(hào)密碼安全性更高也不用擔(dān)心密碼驗(yàn)證碼變動(dòng)導(dǎo)致腳本失效。不過(guò)要落地這個(gè)方案需要你們公司W(wǎng)eb應(yīng)用的開發(fā)配合在系統(tǒng)里接入飛書登錄邏輯。如果系統(tǒng)本身有研發(fā)團(tuán)隊(duì)這個(gè)改造并不大。改造完之后影刀的登錄步驟就可以從“輸入賬號(hào)密碼”簡(jiǎn)化為“等待免登跳轉(zhuǎn)”穩(wěn)定性提升非常明顯。6.3 影刀代碼遷移和跨團(tuán)隊(duì)復(fù)用最后說(shuō)一個(gè)很現(xiàn)實(shí)的問(wèn)題很多公司的RPA腳本最初是個(gè)人業(yè)余時(shí)間搭的后面要交給團(tuán)隊(duì)或者遷移到統(tǒng)一管理環(huán)境里。熱詞里也有“影刀腳本遷移到另外一個(gè)公司上怎么操作”說(shuō)明大家確實(shí)遇到了這類需求。影刀本身提供了導(dǎo)出和導(dǎo)入流程的功能導(dǎo)出的文件可以在另一臺(tái)安裝了影刀的機(jī)器上直接導(dǎo)入運(yùn)行。但在遷移時(shí)有幾個(gè)地方要格外注意流程中引用的文件路徑、Excel路徑都是絕對(duì)路徑換機(jī)器后需要重新調(diào)整。網(wǎng)頁(yè)登錄的Cookie不會(huì)一起遷移新環(huán)境第一次運(yùn)行需要手動(dòng)登錄一次。如果目標(biāo)機(jī)器屏幕分辨率不同可能會(huì)影響部分基于坐標(biāo)定位的元素建議統(tǒng)一用元素定位方式。如果要用飛書消息推送要把Webhook和密鑰這些敏感配置單獨(dú)抽出來(lái)放到環(huán)境變量或配置文件中便于不同環(huán)境切換。影刀也有代碼遷移工具在較新版本里已經(jīng)支持一鍵導(dǎo)出項(xiàng)目配置。建議遷移后在小范圍先跑一周的觀察期每天核對(duì)數(shù)據(jù)準(zhǔn)確性沒問(wèn)題再正式全量替代。7. 這套自動(dòng)化方案穩(wěn)定運(yùn)行的核心經(jīng)驗(yàn)說(shuō)完具體的實(shí)現(xiàn)步驟我把幾個(gè)月實(shí)操下來(lái)最核心的經(jīng)驗(yàn)做一次濃縮總結(jié)。第一日志是最便宜的保險(xiǎn)。我在整個(gè)流程里幾乎每個(gè)關(guān)鍵節(jié)點(diǎn)都埋了日志包括開始時(shí)間、數(shù)據(jù)抓取量、匯總條數(shù)、文件大小、發(fā)送結(jié)果。不要嫌麻煩等到出了問(wèn)題這些日志就是你唯一的排查線索。第二主動(dòng)加一個(gè)“自動(dòng)發(fā)不出來(lái)就報(bào)警”的機(jī)制。除了前面提到的第二套兜底流程我還在影刀里配置了一個(gè)單獨(dú)的條件分支如果主流程里的發(fā)送請(qǐng)求連續(xù)失敗3次就直接調(diào)用一個(gè)獨(dú)立的Webhook發(fā)一條帶“失敗”關(guān)鍵詞的告警消息給運(yùn)維群。這樣領(lǐng)導(dǎo)那邊的日常群不會(huì)收到失敗的報(bào)錯(cuò)但負(fù)責(zé)的人一定能看到問(wèn)題。第三數(shù)據(jù)準(zhǔn)確性驗(yàn)證不能只看“有沒有發(fā)”。自動(dòng)化最重要的不只是“流程跑了”而是“結(jié)果對(duì)不對(duì)”。我的做法是在影刀匯總數(shù)據(jù)時(shí)順帶每次把總行數(shù)、總金額這些關(guān)鍵指標(biāo)和昨日的做一次對(duì)比如果偏離超過(guò)閾值比如50%則在消息里附加一條“異常波動(dòng)提醒”提醒人工復(fù)核。這一步雖然簡(jiǎn)單但能避免很多“發(fā)了錯(cuò)誤數(shù)據(jù)”的尷尬場(chǎng)景。第四所有外部接口調(diào)用都應(yīng)該有超時(shí)和重試而不是永遠(yuǎn)掛死。影刀的代碼塊里requests請(qǐng)求加上timeout參數(shù)連接失敗時(shí)走重試邏輯。寧可多等一分鐘重試也不要卡住整個(gè)流程。這個(gè)方案上線以來(lái)我最大的體會(huì)是自動(dòng)化并不是把活推給工具就完事了它需要你持續(xù)地觀察、調(diào)優(yōu)、加固。但一旦穩(wěn)定下來(lái)那種“每天到點(diǎn)自動(dòng)完成人只需要看結(jié)果”的狀態(tài)確實(shí)非常舒適?,F(xiàn)在每天早上到工位我習(xí)慣性先看一眼飛書群數(shù)據(jù)已經(jīng)在群里整整齊齊躺著這就是RPA加飛書組合給我?guī)?lái)的最直接的改變。如果你也在被各種重復(fù)性的報(bào)表推送困擾不妨按這套流程先搭一個(gè)最小可用版本跑通之后再逐步豐富細(xì)節(jié)。自動(dòng)化這種東西啟動(dòng)永遠(yuǎn)比追求完美更重要。