爬蟲程式 Takami 的感想文
作品展示。另外,取名為 Takami 的原因,是 LoveLive Sunshine 的主角高海千歌。
一切是因為看了鐵人賽的文章才想到的:看了鐵人賽的文章,才發現爬蟲沒有我想像中的那麼困難:無非就是發出請求、擷取回應、針對回應抓取文字。
身為一位 Love Liver 平時興趣聽 Love Live 的歌也很正常。但是,如果每首歌都要搜尋、複製、貼上的話…我曾經做過,那是個酷刑……
看了鐵人賽的文章,我想自己應該也能做一個。
所以就開始吧。用 Aozora Jumping Heart 來做示範。
如果想聽音樂,我們的行為將是點選 Audio 裡面那個稱為 的按鈕。
那麼,它怎麼玩呢?難道是給 JSON API 嗎?
網路告訴我它直接給了 .ogg
檔案播放,沒有 .json
檔案被傳送。這意味著,按鈕裡面很可能直接包含來源網址。
那我們把網頁原始碼打開來看吧:
<span class="ogg_custom aqours">
<div id="ogg_player_1" class="ogg_player">
<div>
<button onclick="if (typeof(wgOggPlayer) != 'undefined') wgOggPlayer.init(false, {"id":"ogg_player_1","videoUrl":"https://vignette.wikia.nocookie.net/love-live/images/e/e6/Aozora_Jumping_Heart.ogg/revision/latest?cb=20160716075746","width":180,"height":35,"length":284,"linkUrl":"/wiki/File:Aozora_Jumping_Heart.ogg","isVideo":false});" style="width: 180px; text-align: center" title="Play sound"><img src="/extensions/OggHandler/play.png" alt="Play sound" width="22" height="22"></button>
</div>
<div>
<a href="/wiki/File:Aozora_Jumping_Heart.ogg" class="image" title="About this file"><img src="/extensions/OggHandler/info.png" alt="Aozora Jumping Heart" width="22" height="22"></a>
</div>
</div>
</span>
注意一下 <button>
裡面的標籤:
onclick="if (typeof(wgOggPlayer) != 'undefined') wgOggPlayer.init(false, {"id":"oggplayer1","videoUrl":"https://vignette.wikia.nocookie.net/love-live/images/e/e6/AozoraJumpingHeart.ogg/revision/latest?cb=20160716075746","width":180,"height":35,"length":284,"linkUrl":"/wiki/File:AozoraJumpingHeart.ogg","isVideo":false});"
裡面放了個有趣的執行程式:wgOggPlayer.init()
。如果你用除錯器(在開發工具內,針對 onclick
屬性的程式碼輸入 debugger
,也就是 onclick=" debugger; if (typeof(
,除錯器就會在開發工具啟動時開始跑除錯器)去追蹤這段程式碼,它會把你帶往一個 JavaScript 的頁面。
那個程式要幹嘛不重要,重要的是裡面有個東西叫做 videoUrl
,它有我們需要的東西:
https://vignette.wikia.nocookie.net/love-live/images/e/e6/AozoraJumpingHeart.ogg/revision/latest?cb=20160716075746
於是,我們知道了。追這個 <button>
標籤裡面的東西準沒錯。
不過,它好像不能用 jQuery 的 $("button")
叫出來啊……怎麼辦呢?
你想到了嗎?$("span.ogg_custom ").html()
啊。這樣就能以字串的形式,叫出裡面的 HTML 了。抓到以後,用正規表達式抓文字不就好了?
我看了幾個檔案,我想我需要這樣:https://vignette.wikia.nocookie.net/love-live/images/(都可以)/(都可以)/(都可以).ogg/
如果要這樣匹配的話,我們的正規表達式就需要這樣:/(https:\/\/vignette.wikia.nocookie.net\/love-live\/images)\/(.*)\/(.*)\/(.*).ogg\//g
- 那個看起來像是 V 的
\/
是/
的跳脫字元,因為/
本身就有表達意義。 (.*)
是一組匹配查詢,它會匹配所有字詞直到斷行、或是為止該組匹配查詢碰上某個東西為止:例如(.*)\/
就是匹配所有字詞、直到/
為止。
最後就是讀 URL 了:拿到歌曲 URL 以後,就可以讀取 URL 裡面 span.ogg_custom
的 DOM 了。
不過有點小插曲:我們用的 request
套件,它請求是非同步的,所以基本上是先到先贏,而不按照順序。如果順序會亂跳的話,又要怎麼知道第幾首呢?
索性也不難:在迴圈裡面加個變數檢查就好。
好的,就這樣完成了。