簡(jiǎn)報(bào)自動(dòng)化系統(tǒng))
每天早上一睜眼就刷新聞刷完一圈發(fā)現(xiàn)要么是標(biāo)題黨要么是三天前的舊聞?wù)嬲杏玫男袠I(yè)動(dòng)態(tài)早就被鋪天蓋地的內(nèi)容淹沒(méi)了。我項(xiàng)目里有個(gè)AI方向的調(diào)研需求老板丟給我一句話(huà)幫我盯著AI創(chuàng)業(yè)這塊的動(dòng)態(tài)每天給我整理一份簡(jiǎn)報(bào)。人肉盯新聞根本不現(xiàn)實(shí)我只能順手寫(xiě)了個(gè)腳本調(diào)用新聞?lì)怉PI扔進(jìn)去AI創(chuàng)業(yè)這個(gè)關(guān)鍵詞讓它每天自動(dòng)抓取、自動(dòng)去重、自動(dòng)生成一份Markdown格式的當(dāng)日簡(jiǎn)報(bào)。這項(xiàng)目做完之后已經(jīng)穩(wěn)定跑了好幾個(gè)月過(guò)程踩了不少坑我把它完整拆開(kāi)講講。這套東西本質(zhì)上做的事其實(shí)不復(fù)雜關(guān)鍵詞輸入、API請(qǐng)求、數(shù)據(jù)清洗、按固定模板輸出。難的點(diǎn)在于穩(wěn)定和好用——API不返回?cái)?shù)據(jù)了怎么辦、關(guān)鍵詞命中了一堆無(wú)關(guān)內(nèi)容怎么辦、免費(fèi)額度用完了怎么辦這些才是真正磨人的地方。我把整個(gè)過(guò)程、代碼思路、參數(shù)選擇邏輯和踩坑實(shí)錄全部記錄下來(lái)新手照著搭能少走很多彎路。1. 項(xiàng)目拆解與整體思路1.1 這個(gè)項(xiàng)目到底解決了什么問(wèn)題先別急著寫(xiě)代碼想清楚一件事你需要的不是調(diào)一個(gè)API而是一條完整的信息流水線(xiàn)。拿AI創(chuàng)業(yè)這個(gè)關(guān)鍵詞舉例如果你只是簡(jiǎn)單調(diào)一次新聞API拿到的一定是大量噪聲——平臺(tái)隨手發(fā)的一條融資快訊會(huì)進(jìn)來(lái)標(biāo)題里帶AI的無(wú)關(guān)科技八卦也會(huì)進(jìn)來(lái)甚至半個(gè)月前的舊聞都會(huì)被翻出來(lái)。我最早第一版腳本就是這樣跑出來(lái)的簡(jiǎn)報(bào)慘不忍睹七條里有三條跟創(chuàng)業(yè)沒(méi)關(guān)系。所以整個(gè)項(xiàng)目的核心難點(diǎn)并不在API調(diào)用本身而在數(shù)據(jù)過(guò)濾的規(guī)則設(shè)計(jì)、時(shí)效性控制、以及輸出格式的可讀性。另一個(gè)容易被忽視的需求是每天自動(dòng)。抓一次、兩次沒(méi)有意義定時(shí)任務(wù)才是這個(gè)項(xiàng)目的靈魂。搭配上調(diào)度機(jī)制之后它才算真正替代了人肉盯新聞的動(dòng)作。這個(gè)項(xiàng)目的整體鏈路分四段關(guān)鍵詞配置 → API請(qǐng)求 → 數(shù)據(jù)清洗 → 簡(jiǎn)報(bào)生成。每一段都有獨(dú)立的坑后面我一個(gè)一個(gè)講。1.2 為什么選API而不是直接去網(wǎng)頁(yè)抓取拿到需求之后我其實(shí)猶豫過(guò)兩個(gè)技術(shù)路線(xiàn)直接寫(xiě)爬蟲(chóng)去各大科技媒體抓頁(yè)面的方式還是用新聞API的方式。直接抓網(wǎng)頁(yè)的誘惑是新聞源可控、內(nèi)容全、不依賴(lài)第三方接口。但實(shí)踐過(guò)一次就知道有多惡心。目標(biāo)網(wǎng)站的HTML結(jié)構(gòu)經(jīng)常變一個(gè)class類(lèi)名改了你的解析器就廢了反爬機(jī)制越來(lái)越強(qiáng)請(qǐng)求頻率稍高就被封IP為了應(yīng)付不同的站點(diǎn)你得寫(xiě)不同的解析代碼維護(hù)成本直線(xiàn)上升。某個(gè)站今天改版了整個(gè)鏈路斷掉這種不確定性對(duì)日?qǐng)?bào)系統(tǒng)來(lái)說(shuō)是致命的。API方式的優(yōu)勢(shì)是穩(wěn)定和標(biāo)準(zhǔn)化。新聞聚合服務(wù)把采集、去重、分類(lèi)這些臟活累活都做完了你只需要處理好關(guān)鍵詞和參數(shù)就行。輸出結(jié)構(gòu)統(tǒng)一出錯(cuò)概率低維護(hù)起來(lái)也很輕松。代價(jià)是——免費(fèi)的API在請(qǐng)求配額、歷史數(shù)據(jù)時(shí)長(zhǎng)、返回字段上都有限制。但在抓取最新的行業(yè)新聞這個(gè)場(chǎng)景里免費(fèi)額度基本夠用是性?xún)r(jià)比很高的選擇因此我會(huì)選API方案。2. 新聞API選型與參數(shù)解析2.1 主流新聞API怎么選市面上的新聞聚合接口分成幾類(lèi)一類(lèi)是大而全的通用新聞API覆蓋面廣但中文內(nèi)容質(zhì)量和行業(yè)垂直度一般一類(lèi)是垂直領(lǐng)域的數(shù)據(jù)服務(wù)比如專(zhuān)門(mén)做創(chuàng)投、科技資訊的數(shù)據(jù)好但接入門(mén)檻和價(jià)格都高還有一類(lèi)是各門(mén)戶(hù)自帶的開(kāi)放接口穩(wěn)定性看平臺(tái)心情不推薦作為主力源。我實(shí)際的篩選標(biāo)準(zhǔn)就三條第一是否支持中文關(guān)鍵詞檢索返回結(jié)果里中文新聞的比例要說(shuō)得過(guò)去第二免費(fèi)檔位的每日請(qǐng)求次數(shù)夠不夠你跑多個(gè)關(guān)鍵詞——如果一天要跑好幾個(gè)關(guān)鍵詞很快就超了第三返回字段是否包含發(fā)布時(shí)間、來(lái)源、摘要、鏈接這幾項(xiàng)基本配置少了任何一個(gè)都會(huì)讓簡(jiǎn)報(bào)制作變得非常別扭。我的選擇落地之后是這樣的用一個(gè)通用新聞API作為主數(shù)據(jù)源把請(qǐng)求頻率控制在每分鐘幾次、每天累計(jì)請(qǐng)求數(shù)控制在免費(fèi)額度內(nèi)。同時(shí)留了一個(gè)備用源配置主源出問(wèn)題時(shí)自動(dòng)切換。多源策略會(huì)在后面常見(jiàn)問(wèn)題里詳細(xì)介紹這里先記住一個(gè)結(jié)論別把雞蛋放在一個(gè)數(shù)據(jù)源里新聞API掛掉是常態(tài)不是意外。2.2 核心參數(shù)設(shè)置與返回結(jié)構(gòu)解析新聞API的調(diào)用方式大同小異本質(zhì)都是構(gòu)造一個(gè)HTTP GET請(qǐng)求帶上認(rèn)證信息和查詢(xún)參數(shù)。我需要重點(diǎn)解析幾個(gè)核心參數(shù)。q關(guān)鍵詞這是最需要花心思的參數(shù)。直接填A(yù)I創(chuàng)業(yè)會(huì)匹配到大量帶AI、帶創(chuàng)業(yè)但跟主題關(guān)系不大的內(nèi)容。實(shí)際使用中要配合布爾操作符比如寫(xiě)成AI AND 創(chuàng)業(yè)的形式或者用精確短語(yǔ)限定。不同API支持的查詢(xún)語(yǔ)法不完全一樣但思路是一致的通過(guò)詞組和邏輯符把范圍收緊。from / to時(shí)間范圍這個(gè)參數(shù)決定了你拿回來(lái)的是不是昨天的新聞。日?qǐng)?bào)的場(chǎng)景下我一般把 from 設(shè)置為今天零點(diǎn)to 設(shè)置為當(dāng)前時(shí)間這樣天然過(guò)濾掉舊聞。有些免費(fèi)API支持的歷史時(shí)間窗口很短比如只能查最近7天所以一個(gè)準(zhǔn)確的 from 參數(shù)能幫你省不少事。sortBy排序規(guī)則大多數(shù)API支持按相關(guān)性、發(fā)布時(shí)間、熱度排序。我的經(jīng)驗(yàn)是抓新聞簡(jiǎn)報(bào)用publishedAt倒序保證看到的是最新內(nèi)容如果你做的是主題研究報(bào)告想看到的是權(quán)威大稿那就用relevancy。別默認(rèn)使用API自己的默認(rèn)值你永遠(yuǎn)猜不到它的默認(rèn)邏輯是什么。language語(yǔ)言明確指定中文避免混入大量英文內(nèi)容。有些API只在特定參數(shù)里支持語(yǔ)言過(guò)濾不設(shè)置的話(huà)它會(huì)返回全語(yǔ)種的結(jié)果這對(duì)簡(jiǎn)報(bào)是災(zāi)難。pageSize / page分頁(yè)控制每次返回條數(shù)。簡(jiǎn)報(bào)場(chǎng)景每頁(yè)取50條足夠了不要貪多。條數(shù)越多后續(xù)清洗的負(fù)擔(dān)越大而且免費(fèi)API單次請(qǐng)求上限通常就100條。API的返回結(jié)構(gòu)一般是JSON核心字段各家大同小異都會(huì)有一個(gè)articles數(shù)組每條包含title、description、url、publishedAt、source等信息。你拿到的publishedAt通常是UTC時(shí)間不轉(zhuǎn)換就直接寫(xiě)進(jìn)簡(jiǎn)報(bào)會(huì)出現(xiàn)下午三點(diǎn)顯示早上八點(diǎn)的錯(cuò)亂。這個(gè)細(xì)節(jié)放在后面問(wèn)題排查部分單獨(dú)講。3. 自動(dòng)化抓取與簡(jiǎn)報(bào)生成實(shí)現(xiàn)3.1 從零搭建抓取腳本環(huán)境方面我會(huì)用Python因?yàn)樗幚鞪SON、做文本清洗、寫(xiě)定時(shí)任務(wù)都方便。依賴(lài)只有兩個(gè)核心庫(kù)requests負(fù)責(zé)發(fā)HTTP請(qǐng)求schedule負(fù)責(zé)定時(shí)任務(wù)。日志這塊用自帶的logging就行不用額外引入復(fù)雜框架。在寫(xiě)具體實(shí)現(xiàn)之前先把目錄結(jié)構(gòu)規(guī)劃好避免所有代碼堆在一個(gè)單個(gè)文件里后期難以維護(hù)。news_daily/ ├── config.py # 關(guān)鍵詞、API地址、請(qǐng)求參數(shù)配置 ├── fetcher.py # 新聞API調(diào)用與數(shù)據(jù)獲取 ├── cleaner.py # 數(shù)據(jù)清洗與去重過(guò)濾 ├── reporter.py # 簡(jiǎn)報(bào)生成與格式化輸出 ├── scheduler.py # 調(diào)度入口 ├── logs/ # 運(yùn)行日志存放目錄 └── output/ # 生成的日?qǐng)?bào)文件目錄配置模塊先跑起來(lái)# config.py API_ENDPOINT https://api.news-demo.example.com/v1/everything API_KEY your-api-key-placeholder KEYWORDS [AI創(chuàng)業(yè), AI 融資, 大模型 創(chuàng)業(yè)] REQUEST_PARAMS { language: zh, sortBy: publishedAt, pageSize: 50, page: 1, } TIME_RANGE_HOURS 24 # 只取最近24小時(shí)的新聞然后是數(shù)據(jù)獲取模塊核心就是一個(gè)帶參數(shù)校驗(yàn)的GET請(qǐng)求。這里有幾個(gè)必須處理的細(xì)節(jié)請(qǐng)求要設(shè)置超時(shí)時(shí)間避免某個(gè)API卡死導(dǎo)致整個(gè)腳本掛起返回狀態(tài)碼非200時(shí)要做異常處理把錯(cuò)誤信息寫(xiě)進(jìn)日志而不是直接拋錯(cuò)中斷。# fetcher.py import requests import datetime import logging from config import API_ENDPOINT, API_KEY, KEYWORDS, REQUEST_PARAMS logger logging.getLogger(__name__) def fetch_news(keyword: str, time_from: str) - list: params { q: keyword, from: time_from, to: datetime.datetime.now().isoformat(), language: REQUEST_PARAMS[language], sortBy: REQUEST_PARAMS[sortBy], pageSize: REQUEST_PARAMS[pageSize], page: REQUEST_PARAMS[page], apiKey: API_KEY, } try: resp requests.get(API_ENDPOINT, paramsparams, timeout10) resp.raise_for_status() data resp.json() if data.get(status) ! ok or not data.get(articles): logger.warning(f關(guān)鍵詞 [{keyword}] 無(wú)有效返回) return [] return data[articles] except requests.exceptions.Timeout: logger.error(f請(qǐng)求超時(shí): {keyword}) return [] except requests.exceptions.HTTPError as e: logger.error(fHTTP錯(cuò)誤: {e}) return [] except Exception as e: logger.error(f未知異常: {e}) return []函數(shù)返回的是清洗前的原始數(shù)據(jù)列表。注意time_from參數(shù)不是寫(xiě)死的我讓它在調(diào)度入口統(tǒng)一生成保證每天的請(qǐng)求窗口都準(zhǔn)確對(duì)齊最近24小時(shí)。3.2 數(shù)據(jù)清洗與簡(jiǎn)報(bào)生成的邏輯數(shù)據(jù)清洗這一步是整個(gè)項(xiàng)目里性?xún)r(jià)比最高的環(huán)節(jié)它決定了簡(jiǎn)報(bào)的閱讀體驗(yàn)。直接拿API的原始返回出簡(jiǎn)報(bào)的做法我也試過(guò)結(jié)果就是閱讀者要從一堆重復(fù)內(nèi)容里挑重點(diǎn)體驗(yàn)很差。我遇到的第一個(gè)問(wèn)題是平臺(tái)轉(zhuǎn)載重復(fù)。同一家媒體的稿件會(huì)被各個(gè)門(mén)戶(hù)互相轉(zhuǎn)載標(biāo)題或正文高度相似。對(duì) title 做規(guī)范化處理之后用MD5值去重一個(gè)簡(jiǎn)單方案是只保留第一篇。這樣每天能擠掉兩到三成水分。第二個(gè)問(wèn)題是關(guān)鍵詞命中但內(nèi)容跑偏。這需要做一層基于正文片段的過(guò)濾我維護(hù)了一個(gè)簡(jiǎn)單的排除詞列表比如標(biāo)題里只出現(xiàn)AI但正文完全沒(méi)有創(chuàng)業(yè)、融資、產(chǎn)品、落地這些業(yè)務(wù)語(yǔ)義的條目統(tǒng)一標(biāo)記為低相關(guān)度。這個(gè)規(guī)則的邊界需要根據(jù)自己的場(chǎng)景去調(diào)不用過(guò)度設(shè)計(jì)能過(guò)濾明顯噪聲就夠了。第三個(gè)問(wèn)題是內(nèi)容完整度檢測(cè)。description字段為空、url字段為空的條目直接丟棄它們不值得占簡(jiǎn)報(bào)的位置。清洗完之后是格式化輸出。我選擇了Markdown格式的日?qǐng)?bào)原因是它既能方便閱讀也能隨時(shí)轉(zhuǎn)換成HTML。日常實(shí)際使用中被Copy到各種文檔工具里不會(huì)亂版。# reporter.py def build_report(articles: list, keyword: str) - str: lines [f# 每日行業(yè)簡(jiǎn)報(bào){keyword}, ] lines.append(f生成時(shí)間{datetime.datetime.now():%Y-%m-%d %H:%M}) lines.append(f今日收錄{len(articles)} 條) lines.append() for idx, item in enumerate(articles, start1): title item.get(title, ).strip() source item.get(source, {}).get(name, 未知來(lái)源) pub_time item.get(publishedAt, )[:16].replace(T, ) url item.get(url, ) summary item.get(description, ).strip() lines.append(f### {idx}. {title}) lines.append(f 來(lái)源{source} 時(shí)間{pub_time}) lines.append() if summary: lines.append(f摘要{summary}) lines.append(f鏈接{url}) lines.append() return \n.join(lines)3.3 定時(shí)運(yùn)行與部署細(xì)節(jié)腳本能跑通是一回事每天準(zhǔn)點(diǎn)跑是另一回事。我先后試過(guò)幾種定時(shí)方案最終用的是schedule庫(kù)配合后臺(tái)常駐進(jìn)程的方式因?yàn)樗缙脚_(tái)、配置直觀而且出錯(cuò)時(shí)日志排查方便。# scheduler.py import logging import schedule import time from fetcher import fetch_news from cleaner import clean_articles from reporter import build_report logging.basicConfig(levellogging.INFO, format%(asctime)s | %(levelname)s | %(message)s) def job(): keywords [AI創(chuàng)業(yè), AI 融資, 大模型 創(chuàng)業(yè)] all_articles [] for kw in keywords: time_from (datetime.datetime.now() - datetime.timedelta(hours24)).isoformat() raw fetch_news(kw, time_from) cleaned clean_articles(raw) report build_report(cleaned, kw) output_path foutput/{datetime.datetime.now():%Y-%m-%d}_{kw}.md with open(output_path, w, encodingutf-8) as f: f.write(report) logging.info(f關(guān)鍵詞 {kw} 簡(jiǎn)報(bào)已生成: {len(cleaned)} 條) schedule.every().day.at(08:00).do(job) while True: schedule.run_pending() time.sleep(60)注意兩個(gè)細(xì)節(jié)第一文件寫(xiě)入的編碼必須是utf-8否則Windows環(huán)境下打開(kāi)中文內(nèi)容會(huì)亂碼第二每日生成一個(gè)獨(dú)立文件比把內(nèi)容追加進(jìn)同一個(gè)文件更好用這樣做久了之后你能回顧某天的信息后續(xù)要做趨勢(shì)分析時(shí)也有素材。部署層面我選擇放在一臺(tái)低配服務(wù)器上讓它常駐運(yùn)行。因?yàn)闆](méi)有圖形界面資源需求整體的占用相對(duì)有限。服務(wù)器上掛nohup或?qū)懞?jiǎn)單啟動(dòng)腳本即可。如果只是個(gè)人使用Windows任務(wù)計(jì)劃程序配合python scheduler.py也能達(dá)到同樣效果。我的建議是能掛著跑就別手動(dòng)觸發(fā)定時(shí)任務(wù)是這個(gè)項(xiàng)目?jī)r(jià)值的一半。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄4.1 免費(fèi)接口的請(qǐng)求限制與超額處理免費(fèi)新聞API最頭疼的問(wèn)題就是請(qǐng)求次數(shù)限制。我遇到過(guò)不止一次腳本跑到中午就開(kāi)始返回429狀態(tài)碼一看控制臺(tái)原來(lái)免費(fèi)檔位每天只能請(qǐng)求500次。我代碼里為了抓四個(gè)關(guān)鍵詞每個(gè)關(guān)鍵詞做了翻頁(yè)遍歷早早就把限額耗光了。排查后發(fā)現(xiàn)原因有三個(gè)一是翻頁(yè)邏輯寫(xiě)得太貪每次把最大分頁(yè)數(shù)都輪一遍二是沒(méi)有做時(shí)間窗口內(nèi)的請(qǐng)求潤(rùn)滑短時(shí)間密集請(qǐng)求特別容易被限流三是多個(gè)關(guān)鍵詞共用一個(gè)API Key沒(méi)有錯(cuò)峰調(diào)度。解決方案很簡(jiǎn)單。第一嚴(yán)格控制每個(gè)關(guān)鍵詞只取前1到2頁(yè)數(shù)據(jù)日?qǐng)?bào)不需要幾十年前的舊聞第一頁(yè)已經(jīng)是該時(shí)間窗口下最新的一批了。第二在關(guān)鍵詞之間加time.sleep()比如3到5秒把瞬時(shí)請(qǐng)求頻率降下來(lái)。第三在代碼里對(duì)429響應(yīng)做特殊處理捕獲到之后自動(dòng)暫停60秒重試一次而不是直接拉崩。4.2 發(fā)布時(shí)間字段的時(shí)區(qū)錯(cuò)亂問(wèn)題這屬于不看不知道、一看嚇一跳的坑。API返回的publishedAt字段絕大多數(shù)情況下是UTC時(shí)間我最初直接在簡(jiǎn)報(bào)里原樣使用。有一天我早上八點(diǎn)打開(kāi)簡(jiǎn)報(bào)發(fā)現(xiàn)頭條新聞的發(fā)布時(shí)間寫(xiě)著凌晨?jī)牲c(diǎn)我還以為是API數(shù)據(jù)有問(wèn)題仔細(xì)一推才知道是UTC沒(méi)做本地化。正確的處理方式是在清洗階段就把時(shí)間統(tǒng)一轉(zhuǎn)換成東八區(qū)時(shí)間轉(zhuǎn)換邏輯不超過(guò)三行代碼但必須放在數(shù)據(jù)寫(xiě)入簡(jiǎn)報(bào)之前。我建議在cleaner.py里對(duì)所有時(shí)間字段做標(biāo)準(zhǔn)化轉(zhuǎn)換后續(xù)不管換哪家API都不用再改這塊。4.3 關(guān)鍵詞命中不準(zhǔn)的內(nèi)容過(guò)濾策略大部分通用新聞API的文本匹配是比較寬松的你搜AI創(chuàng)業(yè)它可能把AI在醫(yī)療行業(yè)的創(chuàng)業(yè)故事創(chuàng)業(yè)公司用AI做電商這類(lèi)近似主題都帶進(jìn)來(lái)。這看起來(lái)是好事但實(shí)際簡(jiǎn)報(bào)里會(huì)夾雜大量不相關(guān)內(nèi)容反而會(huì)影響閱讀效率。我的做法分三層。第一層在API請(qǐng)求層面通過(guò)加引號(hào)和AND邏輯符收縮匹配只保留同時(shí)包含核心詞的文本。第二層在清洗層面對(duì)標(biāo)題做包含性檢測(cè)標(biāo)題完全不出現(xiàn)業(yè)務(wù)核心詞的直接丟棄。第三層在排序階段把純資訊類(lèi)的泛AI新聞排到最后把標(biāo)題同時(shí)命中融資、發(fā)布、合作、增長(zhǎng)等事件詞的排前面。這套策略做下來(lái)簡(jiǎn)報(bào)的有效信息占比從最開(kāi)始的六成左右提升到了八成五以上。4.4 鏈接跳轉(zhuǎn)失敗與摘要截?cái)嗟奶幚硇侣凙PI返回的鏈接大多是經(jīng)過(guò)跳轉(zhuǎn)的短鏈或追蹤鏈直接放進(jìn)簡(jiǎn)報(bào)里閱讀體驗(yàn)尚可但偶爾會(huì)出現(xiàn)鏈接時(shí)效性問(wèn)題——上午生成的簡(jiǎn)報(bào)下午點(diǎn)擊就提示內(nèi)容不存在。我測(cè)試后發(fā)現(xiàn)這類(lèi)問(wèn)題多出在源站做了內(nèi)容下線(xiàn)或反爬攔截。建議做一層鏈接健康度抽查隨機(jī)抽三條URL做HEAD請(qǐng)求檢查返回狀態(tài)碼狀態(tài)碼異常的直接從簡(jiǎn)報(bào)里替換掉。當(dāng)然不用每條都查那樣太耗配額。摘要截?cái)嗟膯?wèn)題則簡(jiǎn)單得多凡是超過(guò)80個(gè)字符的description字段統(tǒng)一截?cái)嗟綀A滿(mǎn)的句子結(jié)束位置保證簡(jiǎn)報(bào)排版不會(huì)因?yàn)殚L(zhǎng)短不一變得凌亂。前面提到的內(nèi)容整理成速查表方便你排查時(shí)對(duì)照癥狀可能原因處理方式大量429返回請(qǐng)求頻率過(guò)高增加請(qǐng)求間隔限制翻頁(yè)次數(shù)文章時(shí)間全都早于預(yù)期UTC時(shí)間未轉(zhuǎn)本地統(tǒng)一做時(shí)區(qū)轉(zhuǎn)換簡(jiǎn)報(bào)混入大量無(wú)關(guān)內(nèi)容關(guān)鍵詞匹配過(guò)寬加AND邏輯符、過(guò)濾層某幾條鏈接打不開(kāi)源站下線(xiàn)或反爬抽查鏈接狀態(tài)異常即刪除中文標(biāo)題亂碼文件寫(xiě)入編碼錯(cuò)誤指定utf-8編碼寫(xiě)入同一篇文章反復(fù)出現(xiàn)各平臺(tái)互相轉(zhuǎn)載對(duì)title歸一化后MD5去重5. 從日?qǐng)?bào)延伸到更多關(guān)鍵詞與場(chǎng)景5.1 多關(guān)鍵詞并行與自定義輸出模板這個(gè)項(xiàng)目跑通AI創(chuàng)業(yè)之后我很快加了AI 融資和大模型 創(chuàng)業(yè)兩個(gè)關(guān)鍵詞因?yàn)樗鼈冎g存在交叉但沒(méi)有完全被AI創(chuàng)業(yè)覆蓋。配置層面把關(guān)鍵詞列表外置到配置文件里新增一個(gè)關(guān)鍵詞不需要改代碼。輸出模板目前是Markdown如果你的使用場(chǎng)景是發(fā)到IM群里可以考慮把輸出格式切換成HTML或純文本只需要改reporter.py里的字符串拼接邏輯。5.2 結(jié)合摘要和趨勢(shì)數(shù)據(jù)的進(jìn)一步拉寬日?qǐng)?bào)做順手之后可以做的事就多起來(lái)了。比如把每篇文章的標(biāo)題和摘要拼接后調(diào)用文本摘要接口做一個(gè)一兩句話(huà)的核心提煉放在簡(jiǎn)報(bào)標(biāo)題下面這樣打開(kāi)簡(jiǎn)報(bào)第一屏就能掌握今天大概發(fā)生了什么。再比如每天的數(shù)據(jù)都落地到SQLite積累兩三個(gè)月后能統(tǒng)計(jì)出AI創(chuàng)業(yè)相關(guān)資訊在周幾最密集、哪些媒體發(fā)布量最大甚至做一個(gè)簡(jiǎn)單的熱度趨勢(shì)圖。這些都不是難點(diǎn)真正的底座是穩(wěn)定運(yùn)行的抓取鏈路。5.3 推送渠道的替換與擴(kuò)展如果你想把簡(jiǎn)報(bào)從文件變成通知可以去接郵件或者群機(jī)器人。郵件的好處是可以沉淀、可以歸檔聊天機(jī)器人的好處是打開(kāi)率極高適合日??鞉?。我個(gè)人推薦郵件作為主力推送渠道因?yàn)樗母袷郊嫒菪宰詈门虐娌粫?huì)亂。機(jī)器人作為補(bǔ)充發(fā)送摘要即可。6. 最后的幾個(gè)實(shí)操建議這個(gè)項(xiàng)目做完之后我有幾個(gè)體會(huì)。第一日?qǐng)?bào)類(lèi)工具的核心不是功能炫技而是穩(wěn)定。穩(wěn)定跑三個(gè)月的簡(jiǎn)單腳本比功能花哨但每周掛兩次的工程更有價(jià)值。第二控制單次請(qǐng)求的量夠用就好不要試圖一次性把API的可用數(shù)據(jù)全拉回來(lái)少即是多。第三配置和代碼要分離關(guān)鍵詞、API地址、請(qǐng)求頻率都放進(jìn)配置文件改動(dòng)時(shí)不用碰代碼邏輯。還有一個(gè)小技巧我一直留著在被要求再次做個(gè)類(lèi)似項(xiàng)目的時(shí)候使用給每個(gè)API請(qǐng)求打上自定義業(yè)務(wù)標(biāo)識(shí)方便后續(xù)在日志和監(jiān)控里審計(jì)是哪類(lèi)請(qǐng)求出了問(wèn)題這在多個(gè)關(guān)鍵詞并行跑的場(chǎng)景下排查效率尤其高。這個(gè)項(xiàng)目我目前一直在用每天早上的第一件事就是打開(kāi)郵箱看簡(jiǎn)報(bào)三五分鐘就能知道AI創(chuàng)業(yè)領(lǐng)域昨天有哪些值得關(guān)注的消息。其實(shí)做一個(gè)好的自動(dòng)化工具最大的成就感不在于技術(shù)多復(fù)雜而在于你把它設(shè)好后的一整年它都在替你干活。