Huginn中文指南:搭建自己的iFTTT

傳說有兩個烏鴉,名為Huginn和Muninn,它們被視為奧丁的左肩右臂。奧丁在黎明時送出Huginn和Muninn,它們飛到世界各地,然后在晚餐時間回來,告訴奧丁它們看到和聽到的一切,奧丁則賜予它們食物作為報酬。——Huginn命名的由來

什么是Huginn?

Huginn是一個強大的自動化工具,它就像iFTTT,if 1 then 2,當事件1出現,自動完成事件2。它可以幫助你設置感應器,收集信息并完成從信息的搜集—過濾—通知這樣一連串的任務。比起iFTTT,它更加強大,更加自動化,也更加難以搞定。不過,使用Huginn,你可以做到比iFTTT更加多樣、更加有趣的事情,其缺點僅僅是——你需要一筆小小的精力,去學習相關知識,去配置相關程序,去在每天的實踐中debug,讓它成熟起來。

關于Huginn的大概介紹,有兩篇文章寫的很好。我承認,自己的huginn之路就是從這里開始的:不過,我并沒有按照這樣的思路來做,不管怎么樣,首先閱讀以下這些文章,總是有好處的。

第一篇是關于Huginn的大致結構,它是怎么幫助我們完成任務的:

Huginn: 燒錄RSS的神器

我起初了解Huginn是因為想要為沒有RSS的網站制作RSS種子。我嘗試過Feed43,但是免費版本種子更新速度太慢,頻率是六小時一次,通知不及時。加上我特別擔心這些看不清楚盈利模式,同時在CN網絡打開又特別慢的網站,怕他哪一天就完蛋了,在這個時候,我通過百度知道了Huginn。到今天為止,Huginn也還是個“小眾”的東西,在百度的搜索結果,中文頁面只有兩個能看,并且這兩個里面只有一篇教程,這篇教程限制還很多,并且一大群人在下面提issure,各種各樣的安裝錯誤。

Huginn 官方網站/WIKI

里面的安裝寫的是很詳細,不過如果你真的照著做,出問題的概率幾乎是100%。作者們假定你已經了解了Xpath,CSS,JS還有Docker、Negix、Linux基礎,當我剛開始著手準備搭建的時候,我真的感到非常痛苦,各種錯誤出現在各種位置。不過——這顯然也不是作者的問題,當我現在,想要寫一個人人都能看得懂的教程的時候,才發現,這其中的工作量,何其之大,未免生出放棄的念頭。

嘗試部署Huginn到你的服務器

關于huginn的安裝,如果自己沒有服務器的,可以參看這篇文章:

當然,如果英文基礎尚可的話,可以參考一下官方給的安裝資料:

Deploying Huginn 在服務器上部署Huginn

  • Installation guide for Ubuntu/Debian

    我嘗試在在EC2上這樣安裝,嘗試了13遍,最后還是放棄了,國內的話,安裝gem可能會遇到qiang的問題,所以想要在阿里云或者騰訊云上安裝的,請做好心理準備

  • Run Huginn on Heroku

    這個方法和上面提到的中文安裝教程其實是一種思路,部署在第三方平臺。

  • Deployment with Capistrano

    這個也是第三方平臺。

  • Using Huginn on predeployed Docker container

    安裝docker是最簡單的方法,不過之后的配置需要docker基礎,不過一般人也用不到這些高級的設置,所以還是推薦用這種方法安裝,備注:阿里云好像占用了一些端口,安裝docker會有問題,請自行百度更改這些設置,搜索“阿里云安裝docker”就可以。

    Linux安裝指南(最好還是點開鏈接去看官方的wiki)

    Install docker using the install instructions;首先要有docker環境,docker的安裝參考 這里 , 非常簡單。

- Start your Huginn container using  `docker run -it -p 3000:3000 cantino/huginn`
- Open Huginn in the browser `http://localhost:3000`
- Log in to your Huginn instance using the username  `admin`  and password `password`

安裝好之后,就可以進行以下的任務了。

初見Huginn

image
image

Huginn的狀態欄很簡單,agents指的是機器鳥,鳥兒們被分成組,執行不同的計劃,這些分組稱之為scenarios,同一組的鳥兒彼此間互相合作,在一個組里,第一只鳥兒的指令是主人下發的,第二只鳥兒的指令則是從第一只鳥兒執行完指令后生成的事件events中獲取的。換句話說,當一只鳥兒獲取到情報后,它會生成一個事件,同一組的鳥兒可以從這些事件中獲取指令,開始自己的任務。Credentialsservices指這些鳥兒常去的地點,其實就是別的服務程序的API接口,這些鳥兒從這里獲得相關服務的信息。

image

這個是我的agents。點擊 view diagram可以查看相關的agent之間的關系,比如這樣:

image

以右邊為例,第一只鳥兒打開一個網頁,然后獲取到相關的條目url,第二只鳥兒打開這個url,然后從新的頁面里提取全文。要知道,第一只鳥可能獲取多個url,它獲取的這些url稱之為事件event,這些事件被交給第二只鳥,這只鳥比較悲催,需要一個個打開這些事件中的url,然后分別獲取全文,然后再生成與之對應的自己的event。第二只鳥的event里面是獲取到的url內的全文,然后這些內容被交給第三只鳥,第三只鳥把這些內容合起來,生成一個RSS種子,它自己的event,是一個網址,這個網址就是我們最終得到的RSS源。

示例一:當美劇更新的時候推送通知到我的iPhone

0、需求分析

這個任務設計兩大部分,首先是美劇網站更新的檢測,二是如果有更新,把生成的huginn event推送到手機端。第一部分很簡單,利用website agent抓取on_charge的數據即可,第二部分則需要選擇一個服務商,并且將huginn event的內容推送到這個平臺。

這樣的服務商比較不錯的有三個:

  • 郵件agent
  • slack agent
  • pushover agent

其中郵件推送最經濟實惠,不受平臺約束;pushover這個服務最方便,APP界面簡潔美觀,但是需要購買許可,每份許可一次性售價30人民幣。slack是一個和企業微信比較像的國外交流軟件,可能面臨著封殺的危險,但是功能豐富,支持桌面端、Chrome插件、iOS和Android端,界面漂亮,并且可以自己選擇把消息推送到哪一個群組。

因為我不太希望自己的郵箱堆滿消息,所以選擇了slack。

1、獲取美劇信息更新

這一部分很簡單,利用website agent即可。

假設我們需要獲取字幕組的資源,那么我們的網址就應該選擇字幕組的搜索頁面。(因為字幕組的網站需要登錄才能在美劇詳情的頁面顯示資源,提供下載,如果不注冊賬戶則不能看到資源,也就無法判斷目前更新的狀態,但是搜索頁面提供最新更新的“字幕”信息,我們可以在第一時間得知此劇有更新。)

如果有實力的話,建議每次自動登陸自己的賬戶,在美劇的詳情頁查看是否有更新,并且獲取最新更新的地址,自動發送到遠程迅雷等NAS接口并自動下載,然后通過slack通知你美劇有更新并且已經下載好了,不過這樣比較麻煩。

我們先從簡單的開始,website agent 信息如下所示:

sdjtg1
QQ截圖20170120150104

注意,這里選擇mode:on_change即可,比較節省資源。至于url和title的css信息,分別指的是fl-info這個class下的a元素,中間的//指的是a元素包括這個class的子、孫、重孫等,如果使用一個/則表示,這個a元素則僅僅指的是class的子元素(而不能是子元素的元素)。@href表示href屬性,text()表示獲取其文本信息。

這個agent的網址是(2017年):

http://www.zmz2017.com/search?keyword=%E7%A5%9E%E7%9B%BE%E5%B1%80%E7%89%B9%E5%B7%A5&type=subtitle

在沒更換網址之前是這個:

http://www.zimuzu.tv/search?keyword=神盾局特工&type=subtitle

2、創建過濾器

這不是一個必選項。因為,當我們獲取更新后,直接可以把title的內容作為通知的信息發送到我們的手機。但是,一般情況下,當我們獲取了目錄之后,需要過濾掉我們不希望出現的信息,這樣推送的消息會更有針對性。

創建過濾器利用的是TriggerAgent

image

如圖所示,是另外一個任務的過濾器,這里作為實例。keep event這里我選擇的是false,意思是不生成過濾之后的事件,直接傳遞message的內容給下一個agent。如果你希望對過濾后余下的信息進一步利用,比如再次過濾之類,可以選擇true以保留事件。

type指的是類型,regex指的是匹配,系統會檢測上一個agent生成的內容(這里選擇的是path:title,意思是把傳遞過來的事件中的title作為過濾的對象),和value中內容進行比較,如果這個event中包含這些value,那么生成事件,否則不生成。value中的豎分割線指的是或的意思,出現其中任何一個詞即可通過過濾器,生成事件。!regix 指的是不匹配,它會檢測pathvalue的相似程度,如果path中出現value的值,則不輸出,反之,則通過過濾器并輸出、生成事件。

3、通過Slack推送通知

首先,前往https://slack.com/ 注冊一個Slack賬戶。

接著,配置incoming webhook:

前往https://my.slack.com/services/new/incoming-webhook

選擇或者新建一個群組 (channel),點擊繼續,復制Webhook URL ,然后選擇一個標簽(Descriptive Label,可選) 和昵稱(Customize Name),自定義通知的圖標,保存設置。

你的 webhook URL 類似這個樣子: https://hooks.slack.com/services/some/random/characters

image

注意,Sources來源(1處)選擇上一個Agent,這里用的是我們website agent中的神盾局特工更新,當然你也可以用TriggerAgent作為通知的來源。

Propagate immediately(2處)的意思是當上一個Agent生成事件后立馬喚醒此Slack Agent。一般,這樣會造成較高的CPU使用,我選擇不理會這個選項,默認情況下,Huginn會每分鐘檢查一下你的Agent,看有沒有事件需要處理,所以不選的話,頂多1分鐘后再推送消息,對我的差別不大。

webhook_url(3處)選擇剛才我們生成的Webhook URL,channel(4處)選擇我們之前設置的群組(Chanel),username指的是昵稱,message指的是我們需要推送的消息。icon建議留空,這樣它會默認使用你在Slack設置界面中指定的圖標。

如果我們選擇了“神盾局特工”作為此Slack Agent的來源(Source),那么,你在右面會看到這樣一個東西(6處),這里指的是Slack Agent來源事件的Agent,即神盾局特工更新這個Website agent 。下面顯示了此website agent傳遞過來的參數,我們看到有一個url,有一個title,在message欄內填入紅色字部分,那么通知將會變成這個樣子:

更新:[美劇字幕]《神盾局特工 第四季 第十集【精校】》Marvel's Agents of S.H.I.E.L.D 地址是:/subtitle/51114

其中被雙括號包裹的東西是上一個agent中傳遞過來的事件對應部分的內容,其余部分我們可以自己填寫。比如,默認生成的url是/subtitle/51114,我們需要在前面加上http://www.zmz2017.com/,即:

image

這樣一來,我們收到的通知就變成下面這個樣子了。

更新:[美劇字幕]《神盾局特工 第四季 第十集【精校】》Marvel's Agents of S.H.I.E.L.D 地址是:http://www.zmz2017.com/subtitle/51114

看一下我們的流程,是這個樣子的:

image

示例二:為沒有RSS的網站創建訂閱

下面給出我為了獲取ONE的RSS使用的代碼,注意,真正想要了解它的使用方法,僅僅看懂以下代碼是沒什么作用的,每個類型的agent都給出了詳細的使用指南,就在你新建agent的右側,雖然它是英文,請務必讀懂,這非常重要。

1、摘要獲取

單擊任務欄新建一個agent,這里選擇website agent,之后按照要求填入相關信息。注意:agent的名稱是必填項。當你新建一個agent之后,從這個agent的菜單中選擇“show”,你就可以見到如下的agent詳細信息。

Type: Website Agent ;這是一類獲取公開網頁信息的agent

Schedule: Every 5h ;每5小時運行一次,對于RSS來說足夠了

Last checked: ~2h ago

Keep events: 5 days; 保留這個agent生成的事件的時間

Last event created: ~17h ago ;最后事件的創建時間

Last received event: never

Events created: 6 ;創建的事件數目

Event sources: None

Propagate immediately: No

Event receivers: ONE_獲取全文
本agent生成的事件傳遞給誰(因為這個agent是獲取目錄,當然下一步是獲取全文,在新建website
agent的時候你不用填,到下一個生成全文的agent填寫event接收來源就可以了,website
agent會自動把事件接收者指向生成全文的agent)

Working: Yes; 是否工作

Options: ;這里是填入的代碼

{

"expected_update_period_in_days": "2", ;不用管
"url": "http://wufazhuce.com/", ;打開哪個網站
 "type": "html", ;網頁類型,一般是html
"mode": "on_change",
有三種可選,這里指的是把網頁和上一次生成的事件比較,如果有變化則輸出事件,如果和上次輸出的一樣則不輸出,避免生成重復的事件。
"extract": {
"url": {
"css": ".one-articulo-titulo/a", 這里是xpath代碼,前往w3c school自行學習,在xml的目錄下。
"value": "@href"
@XXX表示屬性,這里指的是“a”這個鏈接的href屬性,其實就是指網址。

},

"title": {
"css": ".one-articulo-titulo/a",
"value": "normalize-space()" 這里什么意思,請查看xpath函數部分。

}

}

} 

2、獲取全文

Details

Type: Website Agent

Schedule: Every 5h

Last checked: ~2h ago

Keep events: 2 days

Last event created: ~17h ago

Last received event: ~17h ago

Events created: 2

Event sources: One_一個_摘要獲取

Propagate immediately: Yes

Event receivers: ONE-RSS輸出

Working: Yes

Options:

{
"expected_update_period_in_days": "2",
"url": "{{url}}",
"type": "html",
"mode": "merge",
"extract": {
"author": {
"css": ".articulo-autor",
"value": "substring(normalize-space(),4)"

},

"title": {
"css": ".articulo-titulo",
.XXX表示class屬性,一般不寫成XX[@class=’XXX’],而寫成 “.XXX”
"value": "normalize-space()"

},

"hovertext": {
"css": ".articulo-contenido",
"value": "."

}

}

} 

3、RSS輸出

image
image
  1. 指的是你將要生成的RSS訂閱網址的名稱,它會顯示在地址欄里,請自行填寫(一般寫這個項目的昵稱就好)。

  2. 比如,上一步我們生成的事件內容是:

image

則這里的

image
指的就是上一步生成事件中的title值,因為可能有很多同一agent生成的不同事件,所以這樣表示,可以把所有上一個agent生成的事件結合在一起輸出。

以上。

本文首發于blog.mazhangjing.com ; blog.mazj.me. ? 版權所有,轉載請聯系作者:js@mazhangjing.com

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容