卡尼多隨筆

認識自我 • 感受世界 • 創造價值

0%

抓取某網站特定 URL 並做些處理

👨‍💻 情境題:

身為一名後端工程師,今天團隊指派給你一個任務 —— 找出團隊網站、部落格、GitHub repo 所有有用到像是 https://my.shorturl.com/3lls9f 這樣的短網址,請你拿到它們分別導向的原網址,並用 3lls9f 當作 id,在團隊跟短網址有關的資料庫 table 當中 insert 新的 record 進去,讓團隊能用另外一種短網址服務來做到一樣的事情 (導向原網址)。

這麼做的原因是,團隊即將 sunset https://my.shorturl.com/,也就是在沒有 insert 新 record 的情況下 https://my.shorturl.com/3lls9f 將會無效,因為另外一種短網址服務它會找不到 3lls9f 這個 id 而發生錯誤!

如果是你,你會怎麼做?簡單分享一下我的作法。

以團隊部落格的例子來說

Stack Overflow 是我們的好朋友

1
wget -r -l 0 -nd -R png,jpg,jpeg,gif,mpg,mkv https://blog.myteam.com/
  • 先透過 wget 來抓取所有 https://blog.myteam.com/ domain 底下的 html 檔(因為短網址連結會藏在裡面)
  • -r -l 0:使用 recursive retrieving 的方式來抓,因為 https://blog.myteam.com/ 底下還會有 https://blog.myteam.com/subpage/ 等等 depth 更深的 subpage
    • 那因為 -r (--recursive) 預設的 depth 為 5,我不確定團隊部落格會不會有超過深度 5 的 subpage,所以我還加上了 -l 0 來做 infinite recursion (這邊的 0 相當於 inf)
    • 詳細可透過 man wget 來查找
  • -nd (--no-directories):Do not create a hierarchy of directories when retrieving recursively.
    • 我希望抓下來的檔案能在同一個資料夾層級下,因為我發現不這樣做有些檔案會被忽略掉
    • 像是如果目前已經存在一個叫做 en 的資料夾,要再抓 /en/index.html 的時候,會因為已經有東西叫做 en 而被略過(我那時候是這樣)
  • -R png,jpg,jpeg,gif,mpg,mkv:抓的時候忽略掉 png,jpg,jpeg,gif,mpg,mkv 這些
    • -R 即為 --reject
    • 沒加上這個,我放著等了超過一小時還在跑⋯⋯
    • 原因是因為它不斷在抓跟 WordPress 有關的靜態檔,那些超多的⋯⋯
    • 反正我只需要 html 檔,忽略掉那些根本無關緊要,反而還省了我很多等待時間!

那 GitHub repo 呢?

我是直接用 GitHub 左上角 Search or jump to… 來搜,然後看哪些 repo 被搜出來,我再 clone 下來那些 repo。

拿到檔案然後勒?

Stack Overflow 真的是我們的好朋友⋯⋯

抓出所有短網址,然後彙整成一份清單:

1
grep -ohr "my.shorturl.com/[a-zA-Z0-9._-~]*" * | sort -u > ../output.txt
  • grep 是一款抓取特定 pattern 文字的好工具!
  • -o:Prints only the matching part of the lines.
    • 因為我只需要短網址本身,前後不相關的文字我不需要
  • -h:Never print filename headers (i.e. filenames) with output lines.
    • 檔名在我這個 case 當中根本不重要,擺著反而會干擾到後面的步驟
  • -r:Recursively search subdirectories listed.
    • 上例的部落格是不需要,但 GitHub repo 可就有很多 subdirectories,沒加上這個 option 不行!
  • "my.shorturl.com/[a-zA-Z0-9._-~]*" 是那個短網址的 pattern
    • 沒加上 https:// 是因為我發現有幾個是 http://
  • * (acts as a wildcard) 代表我想找這個目錄底下的所有東東
  • |:透過這個將 grep 的 standard output stream 導到 sort 為它的 input
  • sort -u:為了拔掉重複的 URL(因為有很多重複的)
  • > ../output.txt:將結果輸出成文字檔(for 下一步)

取得原網址

使用「unshorten.xyz - unshorten multiple URLs」這款線上工具來做。

很單純地,就是 copy and paste output.txt 的內容到上面,再將 resolve 出來的原網址們 copy and paste 到本地端。

本來是想說要不要用 Python 寫個 script 來做,但居然已經有人做這個服務,就不用再多此一舉了😂

存進資料庫

找團隊有用到跟短網址 table 寫入有關的 function 的 repo 和相對應的 route,copy and paste 成一個新的 path,npm run dev 跑起來以後,借助 Postman 來 call 那隻 API,原因是短網址和原網址清單的文字檔在本地端,利用這樣的方式,就能透過 fs module 來讀,拿到相對應的短網址和原網址以後,藉此 insert 新 record 進 DB。


原本以為這個 task 會有大量的「重複性人工操作」,沒想到居然能找到比較優雅的做法,也是挺有意思的~