爬蟲程式 Takami 的感想文

作品展示。另外,取名為 Takami 的原因,是 LoveLive Sunshine 的主角高海千歌

一切是因為看了鐵人賽的文章才想到的:看了鐵人賽的文章,才發現爬蟲沒有我想像中的那麼困難:無非就是發出請求、擷取回應、針對回應抓取文字。

身為一位 Love Liver 平時興趣聽 Love Live 的歌也很正常。但是,如果每首歌都要搜尋、複製、貼上的話…我曾經做過,那是個酷刑……

看了鐵人賽的文章,我想自己應該也能做一個。

所以就開始吧。用 Aozora Jumping Heart 來做示範。

如果想聽音樂,我們的行為將是點選 Audio 裡面那個稱為 Aqours 的按鈕。

那麼,它怎麼玩呢?難道是給 JSON API 嗎?

網路告訴我它直接給了 .ogg 檔案播放,沒有 .json 檔案被傳送。這意味著,按鈕裡面很可能直接包含來源網址。

那我們把網頁原始碼打開來看吧:

<span class="ogg_custom aqours">
    <div id="ogg_player_1" class="ogg_player">
        <div>
            <button onclick="if (typeof(wgOggPlayer)&nbsp;!= 'undefined') wgOggPlayer.init(false, {&quot;id&quot;:&quot;ogg_player_1&quot;,&quot;videoUrl&quot;:&quot;https://vignette.wikia.nocookie.net/love-live/images/e/e6/Aozora_Jumping_Heart.ogg/revision/latest?cb=20160716075746&quot;,&quot;width&quot;:180,&quot;height&quot;:35,&quot;length&quot;:284,&quot;linkUrl&quot;:&quot;/wiki/File:Aozora_Jumping_Heart.ogg&quot;,&quot;isVideo&quot;: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

  1. 那個看起來像是 V 的 \// 的跳脫字元,因為 / 本身就有表達意義。
  2. (.*) 是一組匹配查詢,它會匹配所有字詞直到斷行、或是為止該組匹配查詢碰上某個東西為止:例如 (.*)\/ 就是匹配所有字詞、直到 / 為止。

最後就是讀 URL 了:拿到歌曲 URL 以後,就可以讀取 URL 裡面 span.ogg_custom 的 DOM 了。

不過有點小插曲:我們用的 request 套件,它請求是非同步的,所以基本上是先到先贏,而不按照順序。如果順序會亂跳的話,又要怎麼知道第幾首呢?

索性也不難:在迴圈裡面加個變數檢查就好。

好的,就這樣完成了。