Userscript:碗都敲破了還沒有新功能,那就自己做吧!

YY
9 min readMay 11, 2019

--

Photo by chuttersnap on Unsplash

寫 userscript 或只是段色色的 JavaScript 塞到瀏覽器 devtool console 也有些時日了,趁著有空來紀錄/分享 JS 與 userscript 的美好以及自己做過的東西,不過我也沒受過專業的訓練或大神的薰陶,所以我想在設計、實作上也不會是什麼 best practice,僅供參考 XD

何謂 Userscript

其實我一開始根本沒聽過這詞,而是到了某天才意識到原來自己寫的東西好像可以稱為 userscript 啊。基本上只要是在 client 端把某段 script 塞到網頁裡去改變了這網頁原本的運作、樣式或是類似爬蟲的功能,都可以稱這段 script 為 userscript

為什麼需要 userscript

追溯到我第一次寫這樣的東西,大概是對 Ingress 瘋狂的時候,為了追殺成就塔煮了坨 600 多行的義大利麵在 Ingress Intel Map 定期去紀錄全台灣每座塔 (Portal) 的 owner

義大利麵的部分

然而這就是為什麼需要或為什麼會有 userscript 的原因,因為官方沒有提供使用者想要的功能 (不論何不合理或合不合法),所以只好自己來

Userscript 可以做什麼

:大部分你想要但網站本身沒有的功能,像是

1.只會 JS 的前端也想要爬資料,但沒有 API

爬教務系統課程清單塞到 Firebase

學校教務系統沒有 Open API,但我想要所有開課資訊,這時候就可以寫段 script 塞到瀏覽器讓他幫我爬再塞進自己的 DB

你可能會說阿不就用 python 寫個爬蟲就好了,但我不會啊QQ,另外是直接在頁面塞 code 可以免於可能會遇到 CORS、登入的問題,所以就先這樣吧

2.沒朋友一起參加活動但我想要序號啊

手遊出活動,要邀請朋友參與才能拿序號換虛寶,可是邊緣人沒朋友R,所以只好再次塞東西進瀏覽器了,拿序號一時爽,一直拿序號一直爽

https://hackmd.io/s/B1pB-7j-z

RO 手遊活動

3.想要抓稀有神奇寶貝

Pokemon go 剛出的時候每天都為了快龍、卡比獸奔波,雖然後來有大家找寶貝、poke5566 幫忙,但常常看到的時候都來不及了,希望有即時通知啊

謎:自己做不就有了 (https://hackmd.io/s/SJOrobrA)

Telegram channel for PKGET

4.想一次看完 Dcard 文章的圖片啊

Dcard 瀏覽圖片的功能只能看同一層樓的附圖,可是我想要一次看完原文跟所有留言內的圖片,然後又一個 userscript 誕生了 (https://github.com/x3388638/dcard-images)

2020–01–10 update: 更多細節請參考下一篇 http://medium.com/@z3388638/74e292e5545b

5.用 Google 彩蛋薩諾斯彈指來回報垃圾發言

如果你還有在用知識+就知道上面不少垃圾、廣告內容,雖然檢舉流程沒有很複雜,不過由於人(ㄗˋ)類(ㄐㄧˇ)的懶墮於是弄了個一鍵檢舉的 userscript,但這樣太單調了所以又加上了薩諾斯效果

https://github.com/x3388638/YahooAnswersSpamReport (第一次嘗試用 webpack 包了些 npm package 進來所以有點肥)

用薩諾斯彈指一鍵檢舉

以上都只是出自於自己的需求而弄出來的東西,當然還可以找到更多實用的 userscript 來套用

如何開發 userscript

釐清需求、資料來源

首先你要知道你要達到的效果是什麼,然後會需要加入、操控哪些 UI 或是從系統、頁面中取出什麼資料,而資料的部分要怎麼取得

比方說蘋_日報不久前改成會員制,沒有登入就看不到新聞內容,但我不想要登入可是我要看新聞,所以先來研究一下新聞內容是怎麼出現或怎麼消失的,聰明如你一定很快的可以發現其實在最初 render 時新聞內容是存在的,而後才透過 JS 把內容砍掉

蘋_日報新聞頁面原始碼 新聞內容
蘋_日報新聞頁面原始碼 刪除新聞內容 script

這下需求都釐清了:目標是讓新聞內容顯示在頁面,需要取得新聞內文,再貼於頁面中,附加頁面中有引入 jQuery,所以可以直接使用,資料來源就是頁面中 JS 還沒執行前的 .ndAtricle_margin p 內容

於是有了這樣的 code,然後貼在瀏覽器 devtool console 就算是個最基本的 userscript 了

$.get('./', data => {
const $doc = $(data);
$('.ndPaywall').remove();
$('.ndArticle_contentBox')
.html($doc.find('.ndArticle_margin p').first().html());
});
anti-paywall userscript

或者你想要跟 UI 有點互動也可以在按下「註冊/登入」後才顯示內文

document.querySelector('.ndPaywall input')
.addEventListener('click', e => {
$.get('./', data => {
const $doc = $(data);
$('.ndPaywall').remove();
$('.ndArticle_contentBox')
.html($doc.find('.ndArticle_margin p').first().html());
});
e.stopImmediatePropagation();
});

工具

當然總不可能每次都要手動打開 devtool 然後把 code 拿來貼,所以我們需要一些工具、資源來管理這些 userscript

自己常用的是 TampermonkeyOpenUserJS,Tampermonkey 對現今主流瀏覽器都有支援,透過這個 extension 可以方便安裝、管理使用中的 userscript,然後用 OpenUserJS 來管理 userscript source code,並且能整合 GitHub webhook ,當有新 commit push 到 GitHub 時可自動推到 OpenUserJS

其他設定

除了 code 本體,還需要加一些 userscript 專用的 meta data,讓 Tampermonkey 這類 extension 可以知道這個 userscript 的資訊,像是

// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://medium.com/
// @grant none
// ==/UserScript==

@match 讓 extension 知道在哪些 URL 下要執行,@grant 可以讓你存取一些方便的 function,詳細的使用方法就不多贅述,其他還有一堆欄位可以參考 Tampermonkey 文件

結論

寫 userscript 要什麼能力

說穿了 userscript 在做的事超過 87% 其實就是前端開發,所以勢必至少要對 HTML、CSS、JavaScript 有些瞭解

再來我個人認為很重要的是 trace code 的能力,為了要能夠在別人的頁面上做修改,必然要先了解相關的架構、事件綁定、流程等等,或是會需要去 call 對方的 API,而 API 當然不會有文件教你怎麼使用,這時就要找到 source code 中是怎麼呼叫 API 的及所帶的參數是怎麼產生的,此外常常要 trace 的是 minify + uglify 過的 JS

(最喜歡愛把變數設為全域的網站了)

跟開發 extension 有什麼差

總目標沒有差,就是要發大財,阿我是說要讓生活更美好、讓人類更懶惰。細節的話因為我也沒寫過 extension,不過理論上就是 extension 可以做出更強大的功能,像 Chrome extension 就能使用許多 Chrome 提供的 API,而且比較是針對瀏覽器新增功能而非針對特定網站

最後感謝你的閱讀,文中若有任何錯誤知識還請糾正,如果你喜歡這篇文章可以拍 10 次手,不喜歡的話可以拍 1 次然後分享給 5 個人

--

--