這是關於DD仔堅持用GAS解決問題的過程。
TL;DR
時間過得飛快,我第一次用GAS寫點什麼是2019年中的時候,之後就沒怎麼接觸,而現在已經2022了,然後疫情依然持續。大概一個多月前逐漸越D越多的我突然覺得,YouTube直播點來點去好麻煩,開很多分頁也不是什麼理想的做法,PTT西洽還有人直接開一堆瀏覽器視窗排列在桌面...。總之,這讓我開始思考如何把想看的直播都弄在同一個畫面上這件事,而且要自動載入,不要工人智慧自己輸入網址(´_ゝ`) 所以我就做了關鍵字搜尋,看看有沒有什麼YT多開工具,就是出現了好幾個可以讓你自己輸入多個網址的頁面,嗯,蒸蚌,顯然這不是我要的。
然後就想說自己寫吧,在查了一些資料後,跟GAS很不熟的我發現它竟然可以輸出HTML,儘管內建的各項API服務都有每日使用額度限制(workspace帳號的quota多於一般帳號),但對我的目標需求而言很夠用,所以就決定試試了。不過,似乎是因為「想透過頻道確認是否直播中」這樣的單蠢單純想法,所以一開始使用了YouTube Data API來嘗試做出雛形,結果很快就悲劇了இдஇ 原來透過API進行搜索是相當昂貴的請求,這每天的扣打只有10,000個單位,做一次搜尋就要消耗100單位,我們DD仔隨便都監視數十個頻道這點扣打肯定是不夠用的啊,所以就不打算用API了。
程式要寫直播也是要看到這裡大概過了一週的時間,然後發現已經有很厲害的網站了:HoloTools、Holodex,介面賞心悅目,功能更是豐富。不過,人家是專業的我是客家的,還是讓我繼續往下探索Google Apps Script可以做到什麼程度吧。在這當下要解決的問題就是,我如何能根據口袋裡那張油油的名單去確認並取得目前進行中的直播網址,在做了一些嘗試、繞了一大圈後,我終於回想(?)起來有官方網站(ゝ∀・)b 這樣就好辦了,直接用UrlFetchApp.fetch()就能拿到schedule。
於是就這樣拼拼湊湊出一個可以根據我寫死在script裡的名單去確認並全部排列顯示的頁面。但還是有很多問題,像是名單寫死要更新就得重新部署,頻道頭像的URL也是同樣情況,如果頻道有更新頭像就會失效,而手動加入的影片則使用預設頭像...於是我有一個大膽的想法:如何透過影片連結取得頻道名稱、頭像等資訊?寫過Python crawler可能直呼簡單,不過,我現在只有UrlFetchApp.fetch()可以用...JS渲染想都別想。Embedded YouTube iframe就更別說了,瀏覽器手裡掐著CORS,iframe裡面的東西只能遠觀不可褻玩。於是又瞎嘗試了一番、繞了好大一圈,還是只能從UrlFetchApp.fetch()回傳的raw data去挖挖看裡面有啥了。接著就是不斷嘗試的過程,說實話想直接在Paas寫crawler來串接(/‵Д′)/~ ╧╧ 但這樣我就認輸咧?爬不到的資料實在讓人很不甘心,終於就在我感到心累想跑去YouTube看VT精華的時候,發現在某個script tag裡面有個叫ytInitialData的變數儲存著JSON格式字串,我要的數據就在這裡面!可是,看得到吃不到,哭啊!UrlFetchApp.fetch()回傳的raw data不知何故,某些符號是呈現ASCII Hex的編碼形式,例如左大括號(curly brackets)就變成「\x7b」,然後又嘗試了一番試圖decode仍是無功而返,決定直接取代處理,因為我心累想跑去看VT精華了它們會導致JSON.parse()莫名解析失敗,同樣內容多次測試,解析失敗的位置都不同...歸剛欸!
所以我說 r 到底有什麼問題R ? ⬇︎
後來決定用Regex取出我要的那一段,JSON.parse()就過了...終於啊(´_ゝ`)
取得頻道資訊的問題解了,後來我就乾脆做了一個可以使用Google帳號登入的公開部署版本,把個人偏好設定與頻道頭像URL透過另外兩個Apps Script同步儲存在spreadsheet和local storage,如此保證失效的頻道頭像URL能得到更新,也很節省UrlFetchApp.fetch()的使用quota,至於個人使用的版本就只有在local storage儲存偏好設定與頻道頭像URL等數據。其實後來還有考慮要把聊天室也嵌入頁面,但實際測試就跟在YouTube頁面一樣糟,大量的留言會造成頁面響應延遲,因為直播要開始了所以其他過於細節的部分太雜亂就省略吧。
跨年的時候還在想如何拿資料,整排都預設頭像囧 ⬇︎
Ref.