Linux下的語音天氣預報指令碼

2021-04-25 14:53:06 字數 3305 閱讀 4017

本文映象自作者blog:http://www.csksoft.net/blog/post/linux_weatherforecast.html

這是最近我剛在家裡部署的乙個程式,主要功能就是在每天的特定時間(7:30 以及 18:30 )計算機將自動用中文人聲朗讀出當天以及後一天的天氣情況/預報。天氣預報的資訊由程式採集自中國氣象網(weather.com.cn)。如果你對此感興趣,不妨了解下這篇文章。

其實類似的應用網上應該也不少,我完成這個應用其實大部分精力也並不是花在天氣預報的採集上。而是解決如何將windows的tts引擎(ms sapi)「移植」到linux上,以及編寫相關的服務框架程式。同時,這個應用實際上只是我之前提過的智慧型化家庭系統(ihes)的乙個小應用,所以這次也會連帶著發布ihes framework的一些**(比較簡陋,看過算過,哈哈)。在給出具體的程式**之前,我將一步步介紹其中的一些細節問題,以便有興趣的人自己實現類似的功能。

前文已經提到,我使用的是weather.com.cn的資料。實際上這部分工作是通過乙個bash script來完成的。從該**抓取並提取我們需要的天氣資訊的乙個難點是如何從內容繁多的html**中有效的篩選我們要的內容。這裡我偷了下懶,通過觀察他們**,我發現其wap版本**內容簡單,特別適合抓取:http://wap.weather.com.cn/wap/

基本除了我們需要的天氣情況外,只有寫簡單的關於資訊,而且主要都使用了文字。這裡以我家所在地:上海松江為例,分析資訊提取過程:

該**wap版不同城市以及預報範圍的組織很簡單,僅僅通過url位址來標示,比如上海松江24小時(當天)的預報資訊頁面位址為:http://wap.weather.com.cn/wap/58462/h24/ 而對應的48小時天氣預報(第二天)位址為:http://wap.weather.com.cn/wap/58462/h48/ 。很明顯,前面的58462應當為地區的區域**,而預報範圍就是後面的h。因此,實現當天以及第二天的預報提取,只要抓取這2個位址即可。

對於還不熟悉linux環境的朋友,可以在shell裡面輸入man curl來參看該命令相關資訊。直接通過curl即可將對應html輸出到stdout。

接下來要做的就是僅提取出我們需要的預報資訊,比如:

2023年3月15日 星期天:

[農曆二月十九]:

松江  :

天氣:晴 :

氣溫:17度到4度:

風向風力:西南風4-5級轉3-4級:

紫外線指數:中等:

我做的處理首先是過濾掉所有html標籤,觀察curl抓取的html**可以發現我們需要的資訊沒有被html tag包含,經過這一步處理,輸出的文字中含有可讀文字了。接下來需要將空白行去除。最後僅提取我們需要的文字所在的其實行以及終止行即可。這裡採用sed過濾。這樣一來,最終的處理命令為:

這樣便可得到上面要求的文字輸出了。

一定要採用sapi主要還是因為linux下面我沒找到原生的中文tts庫。因此只好想辦法利用windows下面的資源了。辦法其實也很簡單,用wine... 這裡所說的部署,是指同樣通過wine執行自己編寫的windows程式呼叫部署在linux下的tts engine來進行朗讀。實際上就是進行sapi com元件以及需要的tts engine com元件的註冊工作。這裡有乙個偷懶的辦法:http://www.linuxdiyf.com/viewarticle.php?id=121686

接下來要做的其實就和windows下一樣了,開啟vc寫一段sapi的呼叫程式吧...

不過其實問題要複雜些,存在兩個困難:

該windows程式如何與原生的linux程式/指令碼互動(基於wine)

sapi依賴視窗訊息,需要x-windows環境

可能對一部分人第二個並不是什麼問題,不過我目前家裡用作伺服器的機器配置比較老,為節省資源平時完全禁用了xserver。我又沒心思去修改wine來解決這個問題,所以xserver是必須啟動的了,那麼需要將他的資源消耗盡可能減少。而對於第乙個問題,我的解決辦法是將tts發音功能做成乙個c/s構架的體系。提供乙個./readit的命令,該命令為linux的native程式,readit將需要朗讀的文字用tcp報文傳送給基於windows(wine)的server程式完成真正的合成朗讀。同時我發現每次載入/結束使用sapi的程式,所在的xserver的虛擬記憶體都會無故增加。因此c/s構架是的server常駐系統也避免了潛在的記憶體洩露。還有乙個好處就是在區域網內任何機器都可以呼叫該tts功能。具體的實現這裡就不給出了,有興趣的可以去看源**。文末給出了readit的linux/win32版本。我的實現中,readit支援如下2種方式呼叫:

./readit

echo "text to read by pipe" | ./readit

後者的好處在於能夠朗讀超過命令列引數長度限制的文字,同時能很好的結合前面介紹的指令碼。linux需要終端設定為utf-8編碼。

對於tts engine的選擇這裡就不介紹了,大家選擇比較合適的版本即可(windows自帶的那個中文男聲其實不怎麼樣),我採用了上次earts中運用的tts引擎。

在上面幾個問題解決後,就是部署問題了,我把天氣預報獲取的指令碼抽象成命令getweather( 24 | 48 )。要朗讀明天的天氣,採用命令

./getweather 48 | readit

即可。在執行該命令前要確保我們的tts server已經啟動了。因為server部分依賴於wine和xserver。這裡用下面命令來完成server的載入:

x :3 -ac &

sleep 60

export display=":3" && wine win_voice.exe  1>/dev/null 2>&1 &

其中win_voice.exe就是tts server。可以在開機時配置該指令碼。不過要注意指令碼執行的當前使用者要和部署tts時,wine所在的使用者要一致。

注意,僅供個人參考,不可用於商業用途。

部分天氣預報指令碼

合肥 width 178 height 21 marginwidth 0 marginheight 0 hspace 0 vspace 0 frameborder 0 scrolling no align center id url 修改後 width 278 height 21 marginwid...

樹莓派之天氣預報語音播報

具體實施 前幾天跟同事在聊家裡的 小愛同學 可以語音報天氣,聽起來不錯,也想要乙個。不過嘛,作為技術宅的本人,如果買乙個的話,是不是太low了,於是想到家裡萬能的樹莓派,實現這個功能應該是問題不大的。開始了折騰。原則1 不對樹莓派硬體進行大的改動 原則2 我們一定要用開源或者免費的方案 要獲取天氣預...

天氣預報的獲取

好久沒有寫技術文章了,2010年工作太忙,奔波在國內各地,也沒什麼時間關注一些技術方面的事情,最近有乙個專案封閉開發,有些時間來寫些瑣碎的東西,就當是整理下最近的東西吧,沒什麼技術價值,純粹玩玩而已。本篇是獲取qq天氣預報資訊,獲取的是杭州的當天天氣,如果需要獲取未來三天以及其他城市的,做成配置即可...