最近在改寫自己的 噗浪下載程式,發現噗文連結並沒有在 API response 內,因此尋找了一下,此篇文章則是記錄過程及思路。
每篇噗文右下角向下箭頭點開,有個開啟網址的連結,可以連到單篇噗文的網頁,網址後段是 /p/xxxxxx
。後面的 x
包含英數,看起來像是亂數或是雜湊值產生,初步猜想是後端生成。
尋找流程
查看
/TimeLine/getPlurks
(取得噗文列表)、/Responses/get
(取得單篇噗文回應),這兩支 API 回傳資料都沒有找到對應字串。使用瀏覽器 DevTools 的網路,看原始 html 內容,也不是後端 render 回傳,因此判斷是 JavaScript 產生。
以下截圖皆為 Firefox,使用檢測元素指到 開啟網址 元素,class 是
pif-outlink
,JavaScript 通常會使用 css selector + class name 來進行操作。切到 DevTools 除錯器,按 Ctrl+Shift+F 搜尋現在網頁所載入的所有資源,在一個 minify 過的 js 內找到這個 class。點左下的大括號來將 js 排版一下,雖然變數命名沒有改變,但至少可以看到比較清楚的排版。
產生連結的方式是
o.toString(36)
,再往上找到o
的定義,o = r(s)
。繼續往上,
r
的定義是一個 function,.data()
是 jQuery 來取得某元素 data-attribue 的方法,因此可以判斷e(s)
是某一個元素。最後可以得知,一開始的
o
會回傳某一個元素的data-pid
attribute。回到 DevTools 檢測器,搜尋
data-pid
,發現每一個噗文最外層 div 有這個 attribute,而這個 pid 其實就是 API 回傳的plurk_id
。一開始產生連結的方法是
o.toString(36)
,查了 MDN 的定義,是產生 n 進位的字串,把值丟進去跑,就可以產生對應的字串了。$ Number(1500449470).toString(36) "otbu7y"
最後要轉成 Python code,Python 有內建 hex()
轉換 16 進位文字,但是沒有支援 36 進位,因此使用 mod 和整除的方式來 簡單實作 一下,完成!