用 RSS Bridge 的 CssSelectorBridge 產生出 feed

Hacker News 上看到「Generate RSS feed for any website using CSS selectors (rss-bridge.org)」這個,裡面的連結是 CssSelectorBridge,看起來是剛併進去的:「Add CustomBridge #3457」。

我拿蘋果日報為例子,網址設為 https://tw.nextapple.com/,文章的選擇器設為 .stories-container article,文章的內容設為 .post-inner p,產生出來的頁面連結裡面就包括了 Atom 以及其他種類的 feed。

對於沒有 feed 的網站可以用這可以工具省下不少功夫,之前寫的 feedgen 裡面有不少東西可以退役 (不過當初是打算練 Python,有額外的目的...)

用 Atom feed 訂閱 crt.sh 的 Certificate Transparency

本來打算自己寫個程式訂閱 Certificate Transparency 的資料,結果發現 crt.sh 本身就有提供 Atom feed

舉我的例子「crt.sh | gslin.org」來說,對應的 Atom feed 就在 https://crt.sh/atom?q=gslin.org 這邊。

不過 crt.sh 的速度不快,我在使用 Slack 內建的 /feed add 加了很多次才成功,但設定好之後放著收更新就可以了,看起來還算方便。

官方應該是可以把 feed 的筆數壓低,降低對後端 PostgreSQL 的壓力才對,像是只丟最近 30 天的量就好,現在看起來是所有的 entry 都轉成 Atom feed 丟出來...

透過一些簡單的設定,產生 RSS 頁面的 RSS Please (rsspls)

RSS Please 是一套簡單設定 (但應該是對 programmer 簡單),可以把網頁內容轉成 RSS/Atom feed 的軟體。

我把官網上範例的註解拿掉,可以看到你需要去讀 HTML 頁面的結構,然後找出對應的 css selector:

output = "/tmp"

[[feed]]
title = "My Great RSS Feed"
filename = "wezm.rss"

[feed.config]
url = "https://www.wezm.net/"
item = "article"
heading = "h3 a"
summary = ".post-body"
date = "time"

跟我在 feedgen 上用 Python 做的事情其實差不多,他用了彈性換方便性:rsspls 可以簡單設定一些值就生出一個 feed,而我這邊的 feedgen 需要寫一段 code (雖然不長);但因為 feedgen 是用 Python 處理事情,所以可以不只可以讀 HTML 也可以讀 JSON API,另外也可以設計一些轉換邏輯 (像是 summary 的部份)。

但有人寫起來推廣總是不錯...

自己刻 RSS 2.0 的簡單方式

Lobsters Daily 上看到在介紹 RSS 2.0 的文章:「Implementing RSS for my blog (yes, this one!)」。

大多數我們都會選擇用 library 來輸出 RSS feed 或是 Atom feed,但這並不代表自己己幹 template 會很難,只要處理好 XML 的輸出就可以了。

作者分成兩塊介紹,第一塊是這個 RSS feed 是什麼,第二塊是這個 RSS feed 裡面有什麼。

第一塊的部份是描述 channel 本身的資訊,另外可以看到 {{{items}}} 這段,這是等下要放第二段的部份:

<rss version="2.0">
    <channel">
        <title">title}}</title">
        <link">{{link}}</link">
        <description">{{description}}</description">
        <language">en-US</language">
        <pubDate">pubDate}}</pubDate">
        {{{items}}}
    </channel">
</rss">

接下來就是解釋 items 的部份,裡面可以有很多 item 資料:

<item>
    <title>{{metadata.title}}</title>
    <link>{{getFullUrl slug}}</link>
    <description>{{metadata.summary}}</description>
    <author>mail@nsood.in</author>
    <pubDate>{{rssDatetime metadata.time}}</pubDate>
</item>

你可以靜態寫到檔案裡面,也可以動態產生這個內容,這樣基本上已經會動了。當然,要記得該有的 XML escaping 要放進去。

另外我之前有提到「實做 RSS/Atom feed 的最佳實踐」,也可以參考看看,這算是多做的部份,可以讓 feed crawler 更新速度變得比較即時。

實做 RSS/Atom feed 的最佳實踐

前陣子看到的文章,在講實做 RSS/Atom feed 的 best practice:「RSS Feed Best Practises」。

最簡單的當然還是丟個 Atom feed 就好,接下來就是一些延伸出來可以多做的事情。

首先有提到 discovery,可以讓 crawler 在抓到 HTML 頁面的時候知道 feed 在哪裡,這對於 user experience 來說蠻重要的,大多數的 feed reader 都可以透過這個方式抓到真正的 feed 位置。舉個例子來說,我丟 https://blog.gslin.org/ 進 feed reader,可以透過 discovery 的方式告訴 feed reader 我的 feed 位置在 https://blog.gslin.org/feed/

<link rel="alternate" type="application/rss+xml" title="Gea-Suan Lin&#039;s BLOG &raquo; Feed" href="https://blog.gslin.org/feed/" />

另外是常見的 cache 問題,這個設起來不算太難,主要是細節很多 XD

後面提到的 WebSub,以前叫做 PubSubHubbub,是一個在 feed 更新後主動通知讓 crawler 來抓的機制。不做的話也還好,現在的 crawler 現在都還蠻聰明的,會針對更新比較頻繁的 feed 常常去確認,但這樣總是會有一些時間差。

不過裡面好像沒提到 Update Services,這是比較早期的方法,走 XML-RPC,雖然也不知道現在有什麼用途了,大概就是這樣所以沒提...

用 CSS Selector 產生 RSS feed

Hacker News 首頁看到「Show HN: RSS feeds for arbitrary websites using CSS selectors (vincenttunru.com)」這個,程式在 GitLab.com 上的「Feed me up, Scotty!」這邊,另外這個專案名稱是在玩 Star Trek 的梗:「Beam me up, Scotty」,然後這邊講的 RSS feed 已經算是通稱了,實際上大家都是輸出 Atom

他用的設定檔格式是 TOML,文章給的範例:

[funfacts]
title = "Wikipedia — did you know?"
url = "https://en.wikipedia.org/wiki/Main_Page"
entrySelector = "#mp-dyk > ul li"
titleSelector = "b"
linkSelector = "b a"

[wikivoyage]
title = "Wikivoyage recommendations"
url = "https://en.wikivoyage.org/wiki/Main_Page"
entrySelector = ".jcarousel-wrapper .jcarousel-item"
titleSelector = "h2"
linkSelector = "h2 a"

feed-me-up-scotty/src/index.ts 這邊看起來是 TypeScript 專案,然後用 browser 帶起 Firefox 來,可以預期會吃不少資源...

另外 Hacker News 的討論裡有另外提到「Feed Creator」,看起來也是個不錯的專案,有免費版與付費版...

路透社的 RSS feed

翻資料才發現路透社的 feed 已經不見了,大概是去年 2020 年六月的事情:「Returning the "killed" RSS of Reuters from the dead」。

不過文章裡面提到的替代方案還蠻有趣的,Google News 上可以透過 filter 條件輸出:

https://news.google.com/rss/search?q=when:24h+allinurl:reuters.com&ceid=US:en&hl=en-US&gl=US

不過測了一下台灣自家的新聞媒體網址,看起來不會動... 把網站改成 news.google.com.tw 也不行,如果沒有提供的還是得自己寫...

使用 RSS 的呼籲

在「Please Add RSS Support To Your Site」這邊看到文章作者在呼籲使用 RSS (這邊應該是包括 Atom)。

主要是 RSS/Atom 算是很成熟的架構了,有很多工具可以閱讀 (RSS/Atom Reader),提昇閱讀的效率。像我是用 Bazqux,另外也有不少人在使用 Feedly... 而除了訂閱外,RSS/Atom 也可以再串出去接其他東西,像是串到 IFTTT 後就可以接上 IFTTT 上面的應用程式。

除了文章作者的呼籲以外,我自己也對我自己常用的網站操作 (在 GitHub 上的 hasname/feedgen 這邊),把網頁結果轉成 RSS/Atom (裡面大多就是去讀 search 相關功能了),這樣有新東西就可以透過 RSS/Atom Reader 讀到...

Hacker News 的三種 feed

Hacker News 上有不少人會貼東西上去,算是個不錯的新聞或是消息來源,但這麼多資料要怎麼挑著看,這邊介紹三種不同更新頻率的 feed 可以訂閱。

第一種是每個禮拜一篇的「n-gate.com. we can't both be right.」,不過這個站的字型故意使用 Comic Sans,會需要拿個 Stylus 改一下,我是改成 sans-serif,就順眼多了...

第二種是每天一篇的「Daily Hacker News」。

第三種是官方的 feed,會一直更新,頻率最高:「Links for the intellectually curious, ranked by readers.」。

我是三個都訂起來,至少討論得很熱的會出現好幾次...

第一次拿 Headless Chrome (Chromium) 出來玩...

前陣子發現 PChome 24h 的輕小說 Atom feed 掛掉了 (在 gslin/pchome24h-feed 這邊),看了一下頁面發現換 url 了,而且從 BIG5 變成 UTF-8 (賀!!!),但變成大量的 js call 產生資料產生頁面 (還不是 ajax 的 JSON),而且有一堆奇怪的 magic number 在裡面 (感覺會因為改版就產生變化 XD),就懶得再自己組出來了,決定玩看看 Headless Chrome 練個功...

Chrome 從 2017 年七月的 59 版就推出了 Headless 功能 (stable channel 的時間),也因此在去年四月的時候 PhantomJS 就決定停止維護下去:「Google Chrome 的 Headless 模式與 PhantomJS 的歷史」。

官方的文件「Getting Started with Headless Chrome」寫的很完整,而且也可以看到 Headless Chrome 把常見的功能都先實做完了。在不另外裝軟體的情況下就可以做很多事情。像是直接把生成好的 DOM 轉成 HTML 丟出來:

chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/

或是把頁面輸出成 PDF,或是輸出成圖片 (screenshot.png):

chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/
chrome --headless --disable-gpu --screenshot https://www.chromestatus.com/

也可以直接開 js console 出來互動:

$ chrome --headless --disable-gpu --repl --crash-dumps-dir=./tmp https://www.chromestatus.com/
[0608/112805.245285:INFO:headless_shell.cc(278)] Type a Javascript expression to evaluate or "quit" to exit.
>>> location.href
{"result":{"type":"string","value":"https://www.chromestatus.com/features"}}
>>> quit
$

在文件後面也提供了大量範例,教你怎麼用 Selenium + WebDriver + ChromeDriver 操作,順著用裡面的範例找一下 Python 會怎麼寫就寫好了... 之後也機會來測試 Firefox 好了 :o