實做 Twitter 同步到 Facebook 的程式

幾個月前 Facebook 把 API 拿掉了,大家都不能用 API 發文,本來想說就放掉這個平台,結果被老人家問怎麼都沒更新,因為老人家都是靠兒子的 Facebook 確認生存,看到沒更新就很擔心... XD

由於 API 沒得用了,所以得自己 hack。這邊先列重點:

  • chromium + VNC 登入後,用 chromium headless + selenium 發文。
  • 對於「網頁的穩定性」來說 (i.e. 常不常改版造成我的程式發文失敗),mbasic(.facebook.com) > m > www。

比較重要的方向就是這些,其他的其實就是磨時間、踩地雷,然後把程式刻出來:「gslin/twitter2facebook」。

第一次拿 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

Firefox 的 Headless 模式

Google Chrome 推出 Headless 模式後,Firefox 也推出了:「Headless mode」。

目前正式版是 55 版,只有 Linux 版本有支援,下一個版本 56 版就會包括 Windows 與 Mac 了:

Headless Firefox works on Fx55+ on Linux, and 56+ on Windows/Mac.

然後大家也都是以 Selenium 為重心,所以使用上應該不會是大問題...

偵測 Chrome Headless

作者因為種種原因,想要偵測 Headless 模式的 Google Chrome:「Detecting Chrome Headless」。

之前因為主要是 PhantomJS,有很多地方跟一般的瀏覽器不同,可以利用這些不同的地方來判斷出是不是 PhantomJS:

Until now, one of the most popular headless browser was PhantomJS. Since it is built on the Qt framework, it exhibits many differences compared to most popular browsers. As presented in this post, it is possible to detect it using some browser fingerprinting techniques.

但從 Google Chrome 59 以後因為支援 Headless,使得大多數的判斷的失效:

Since version 59, Google released a headless version of its Chrome browser. Unlike PhantomJS, it is based on a vanilla Chrome, and not on an external framework, making its presence more difficult to detect.

所以作者找了不少方式想要判斷兩者的相異之處... 不過這些方式看起來不太穩定,加上 Firefox 也在準備了,之後只會愈來愈困難吧 :o

Firefox 在 56 也要支援 Headless 模式

Google Chrome 出了以後 Firefox 決定要跟著出的感覺?慢了好幾拍...:「Support headless mode on Windows」。

目前 stable 版是 54.0,所以再兩個 release cycle 就會看到了... 這樣就有兩個有支援 headless 模式的瀏覽器 (而且底層 engine 不一樣) 可以測試了。現在要測的人可以在 nightly 裡看到了。

Google Chrome 的 Headless 模式與 PhantomJS 的歷史

瀏覽器的 headless 模式讓開發者可以透過 command line 或是 API 界面操作,對於自動化開發測試很有用。而 Google Chrome 將在 59 版 (目前 57 版) 引入 headless 模式:「Headless mode」。

Headless mode allows running Chromium in a headless/server environment. Expected use cases include loading web pages, extracting metadata (e.g., the DOM) and generating bitmaps from page contents -- using all the modern web platform features provided by Chromium and Blink.

To use headless, start Chrome with a command line flag:

$ chrome --headless --remote-debugging-port=9222 https://chromium.org

PhantomJS 則是因為 Google Chrome 決定要支援 headless 模式,主要的貢獻者 Vitaly Slobodin (參考 Contributors to ariya/phantomjs 這邊) 決定退出維護:「[Announcement] Stepping down as maintainer」。

是個功成身退的感覺...

Headless Chromium 已經可以用了...

兩個禮拜前提到的「Headless Chrome」,在剛剛已經看到有人提到 source tree 裡面有「Headless Chromium」了:

Headless Chromium is a library for running Chromium in a headless/server environment. Expected use cases include loading web pages, extracting metadata (e.g., the DOM) and generating bitmaps from page contents -- using all the modern web platform features provided by Chromium and Blink.

Headless Chrome

看到 Chromium 將會推出 Headless 模式:

可以在「Implement a headless mode for Chrome」看到從去年開始一直實作,雖然還沒做完,但看起來還算活躍,之後可以更接近實際環境測試了...