Huginn 监视网站更新并生成 RSS

January 18, 2018   Huginn RSS HyperApp 应用分享

Huginn 是一个类似 IFTTT 的工具,可以按照要求自动完成任务,如监视状态更新、获取网页内容、设置条件触发等。具体的介绍可以看 这里

我们有时候需要获取某个网站更新的信息,例如字幕组更新或是学校教务系统通知,但那个网站可能没有 RSS,只能自己定时上去查询是否更新。像这样的任务,交给自动化工具是最好不过。利用 Huginn,就可以实现我的一个需求:监视网页更新并把更新的条目链接做成 RSS,通过我的阅读器提醒我。

本文示例如何配置 Huginn,以获取武汉大学本科生院「通知公告」栏目的更新,其他网站的配置也是同理。

安装 Huginn

安装这些工具总是一件麻烦的事,但有了 Docker,就可以省下很多事,不必再跟配置环境时的各种出错打交道。这次我使用基于 Docker 的服务器管理应用—— HyperApp

HyperApp 是一个基于 SSH 和 Docker 的自动化部署工具,开发者整理了超过几十个常见应用,将其整理到商店中,您只需要点击一下就会出现可视化的配置界面,然后可以一键安装到您的服务器上。部署应用就是这么简单!

使用 HyperApp 安装 Huginn 的方法请见 此处。本文不再叙述。其他安装方法可以搜索到。

解析网页

安装完成后用浏览器打开 Huginn,点击顶部导航 AgentsNew Agent,打开新建 Agent 的页面。

Type 里搜索 Website Agent,并自行设定 Name,其他可保持默认。在 Schedule 可以设定获取网页信息的间隔。

接下来就要对网页的结构进行分析,打开要监视的 网页,可以看到一个文章列表。现在要做的就是发现文章列表内每条链接的结构,并使用 XPath 语法表达出来。

右击文章列表内的链接,查看元素,发现每个 a 外面都包裹着一个 idlineu9_xli,虽然看起来很有规律,但是我还没找到这样的规律要怎么用 XPath 表达出来。

所以要换一条路走,再观察一下,发现所有链接其实都在 classsubstance_rtr 里面,有这个唯一的 class 就好办了。我可以让 Website Agent 寻找这个页面内 classsubstance_rtr 里面的 li 里面的所有 a。写成 XPath 就会像这样:

//td[@class='substance_r']//li/a
  • td[@class='substance_r'] 表示选取拥有 substance_rclass 属性的 td
  • //td[@class='substance_r']指选取所有匹配的td,不管是不是根元素;
  • //td[@class='substance_r']//li 指选取该 td 下的所有 li,不管 li 是不是根元素;
  • //td[@class='substance_r']//li/a 表示选取该 li 下的 a,并且两者之间没有其他元素包裹。

回到新建 Agent 的页面,点击 Options 旁边的 Toggle View,在 "extract" 下的 "url""css" 里填上刚才写好的路径,用 "value": "@href" 指出网址在 href 里。

同理,在下面的 "title" 中,由于文章链接的标题和地址都在同一个 a 里,所以直接用上面的路径,但是 "value" 的值 "@href" 要改成 "@title"

然后把原本模板里的 "hovertext" 修改为 "date",以获取文章更新时间。回到网页里,看到更新时间是在与 a 同级的 span 里,所以把 XPath 路径里的 a 修改成 span。但是网页里的时间是显示成 (01-17) 的样子,需要把它转为 01/17 的形式。这里可以用到 XPath 字符串函数 中的 transfer('abc','b','d'),可以把字符串 abc 中的 b 替换成 d

还得修改 "url" 的值,指向要监视的网页。 最后得到的 Options,是这样的:

{
  "expected_update_period_in_days": "2",
  "url": "http://uc.whu.edu.cn/tzgg.htm",
  "type": "html",
  "mode": "on_change",
  "extract": {
    "url": {
      "css": "//td[@class='substance_r']//li/a",
      "value": "@href"
    },
    "title": {
      "css": "//td[@class='substance_r']//li/a",
      "value": "@title"
    },
    "date": {
      "css": "//td[@class='substance_r']//li/span",
      "value": "translate(translate(translate(., '(', ''), ')', ''),'-','/')"
    }
  }
}

P.S. 其实在 "css" 里还可以写成 CSS 选择器的形式,并不强制使用 XPath。

完成之后可以点击 Dry Run 看看效果,满意就点击 Save 保存。接下来是生成 RSS 的操作。

生成 RSS

New Agent,在 Type 里搜索 Data Output Agent,设定 Name,在 Source 里选择刚刚建好的 Agent 的名字。在 Options 里照样填写:

{
  "secrets": [
    "a-secret-key"
  ],
  "expected_receive_period_in_days": 2,
  "template": {
    "title": "通知公告 - 武汉大学本科生院",
    "description": "通知公告 - 武汉大学本科生院",
    "link": "http://uc.whu.edu.cn/tzgg.htm",
    "item": {
      "title": "{{title}}",
      "link": "http://uc.whu.edu.cn/{{url}}",
      "pubDate": "{{date}}"
    }
  },
  "ns_media": "true"
}

默认的模板里没有 "link""pubDate",所以要自己增加。从之前的输出结果可以看到获得的 url 里面没有网站的域名,所以在这里的 {{url}} 之前把域名加进去。

保存好以后点击顶部导航栏里的 Agents,找到刚才的 Website Agent 右边的 Actions 选择 Run,稍等之后点击刚才的 Data Output Agent,就可以看到输出的两个链接了。

复制 .xml 的链接,直接添加到 RSS 阅读器里,或是托管到 FeedBurner 后添加进 RSS 阅读器里,就获取到这个网站的更新了。

点击顶部导航栏的 Events 可以看到 Website Agent 获取到的所有结果,如果发现输出结果有重复或错误,可以在排错后到这里删除有问题的项目,就不会输出到 RSS 里了。

参考资料

让所有网页变成 RSS —— Huginn

打赏支持

你可以点击 此处,扫描二维码给我打赏两块钱。简单几步,你就能让我在买煎饼时奢侈地多加一个鸡蛋:)