跳到主要內容

[2021 IT鐵人賽] Day 23:專案05 - KKBOX風雲榜02 | AJAX

昨天已經找到的KKBOX用來傳資料的API,也知道各個參數的意義了,今天就實際將資料抓下來吧!

歌曲資訊

回到昨天那個API,是用JSON格式傳遞資料,資料的格式大致如下:

我們可以發現新歌的資料都放在 “newrelease” 之下,一個element就是一首歌的資訊,另外,每首歌的資訊也以key:value的形式整理的很清楚。

接著,就用之前教過的requests.get(url)直接取得API回傳的資料,但回傳的型態是json字串,所以再用Python本身內建的json.loads()函數轉成Python的list和dict資料型態。

# KKBOX華語新歌日榜
url = "https://kma.kkbox.com/charts/api/v1/daily?category=297&lang=tc&limit=50&terr=tw&type=newrelease"
# 取得歌曲資訊json檔
response = requests.get(url)
# 將json字串轉為Python的字典型態
data = json.loads(response.text)

既然已經轉成list和dict的型態了,再根據剛才觀察API得知的架構,要篩選資料就非常簡單,直接來看程式碼:

song_list = data["data"]["charts"]["newrelease"]
# 取得每首歌的排名、曲名、連結、作者、時間
for song in song_list:
    song_rank = song["rankings"]["this_period"]
    song_name = song["song_name"]
    song_url = song["song_url"]
    song_artist = song["artist_name"]
    song_timestamp = int(song["release_date"])
    # 從timestamp轉為日期格式
    song_date = time.strftime(
        "%Y-%m-%d", time.localtime(song_timestamp))

    print("排名:", song_rank)
    print("歌名:", song_name)
    print("連結:", song_url)
    print("作者:", song_artist)
    print("發行日期:", song_date)

發行時間的部分比較特別,因為資料提供的是時間戳記timestamp,所以要另外用time.strftime()函數從timestamp轉為人類習慣的日期格式(年-月-日)。

時間戳記(Unix timestamp)
是一種統一的時間標記方式,代表從1970/01/01累積到現在的秒數,透過這個轉換器可以從timestamp轉成人類習慣的時間標記方式,反過來也可以。
另外有一件有趣的事,因為有些系統的timestamp用32-bits的int儲存,所以在2038/01/19時這個timestamp就會overflow,又被稱為Year 2038 problem。

執行結果:

歌詞

剛才的資訊裡面有一項是連結,而這個連結剛好就是歌詞的連結,隨便挑一首歌,對歌詞的部分右鍵>>檢查,發現歌詞就在class="lyrics"<div>中。

因此,要得到歌詞這樣寫就好了。

song_response = requests.get(song_url)
soup = BeautifulSoup(song_response.text, "html.parser")
lyric = soup.find("div", class_="lyrics").text
print("歌詞:", lyric)

執行結果(抓歌詞因為要get新的網頁,所以會稍微慢一點):

儲存csv檔

儲存資料常用的副檔名除了.txt.json之外,.csv也是常用的儲存格式,像是excel。

因為這次的資料很格式化,剛好就很適合儲存為csv檔。

首先,開啟一個csv檔,編碼記得要為big5,不然只會出現亂碼。newline=''則可以避免一些錯誤。

接著,引用Python內建的csv套件,然後建立一個writer物件,用writer物件的writerow()寫入一行資料,writerow()的參數一定是一個list,list中放要寫入的資料。

歌詞字太多了,放在csv中會很不好看,所以我就不存歌詞了。

import csv

with open('songs.csv', 'w', newline='', encoding="big5") as csvfile:
    # 建立 CSV 檔寫入器
    writer = csv.writer(csvfile)
    # 寫入一列資料
    writer.writerow(["排名", "歌名", "作者", "發行日期", "連結"])
    
    ...
    
    writer.writerow([song_rank, song_name, song_artist, song_date, song_url])

結果:

換個API

還記得昨天講過各個參數的含意嗎? 其實這裡只要將url後面的參數稍微修改就可以得到其他歌曲種類的排行榜哦!

例如:將category改成390,結果就會是西洋歌曲排行榜。

小結

今天告訴你怎麼用Python將API的資料抓下來,並轉成在Python中方便使用的型態,篩選出歌曲資訊後,再利用資訊中的連結取得歌詞,最後將這些資料儲存為csv檔!

這個專案就到這邊,希望你已經學到如何使用AJAX的動態網頁取得資料了,並應用在其他類似的網站上。爬蟲就是這樣,熟能生巧而已,只要爬得多了,自然會有種感覺告訴你該怎麼做。

明天的專案比較大型,預計會分成三天講完,那麼我們明天見~~


如果喜歡這系列文章麻煩幫我按Like加訂閱,你的支持是我創作最大的動力~

本系列文章以及範例程式碼都同步更新在GitHub上,後續會持續的更新,如果喜歡也麻煩幫我按個星星吧~

有任何問題或建議,都歡迎在底下留言區提出,還請大家多多指教。


如果喜歡這篇文章,請訂閱我並且拍五下手給予回饋(使用Google或Facebook帳號免費登入,只需要30秒),資金由LikeCoin提供,完全不會花到各位半毛錢!

因為您的支持,我才更有動力創作出更優質的文章~

留言

這個網誌中的熱門文章

[Python] 關於 with 你所不知道的事

相信用 C 語言寫過檔案讀取的人都知道,經常開檔後就忘記關檔,或者程式中間跳出例外,因此沒有關檔。這些問題常常讓人非常頭痛😱。 所幸 Python 中有 with 這個語法糖,可以自動幫你開關檔,跳出例外也難不倒他,真的非常好用。 但你真的了解 with 背後的運行原理嗎? 🤔 不知道沒關係,因為你現在就會知道了! context manager 在講 with 之前,必須先介紹一下 context manager ,中文可以翻成 情境管理器 。 為什麼叫做 情境管理器 呢? 我們試想一個情境… 當你進入房間時,就要開啟房間的燈:然後當你離開房間時,就要關閉房間的燈。 像這樣理所當然一定要做的事情,我們就稱為一個情境。而 Python 就是透過情境管理器處理這些情境。 要自己實作 context manager 其實很簡單,只要在 Class 中實作 __enter__() 和 __exit__() 即可。 就以進入房間當作例子。 class Room (): def turn_on_light ( self ): print ( "開燈" ) def turn_off_light ( self ): print ( "關燈" ) def __enter__ ( self ): print ( "進入房間" ) self.turn_on_light() return "在房間裡" def __exit__ ( self, exc_type, exc_value, traceback ): self.turn_off_light() print ( "離開房間" ) with Room() as room: ...

[遊記] 2022/07/22 南寮漁港、香山濕地

前言: 2022年的暑假,我來到新竹的工研院實習,因此有了兩個月好好探索這座陌生城市的機會。我在來之前就計畫好了,每周五要選一個地方去旅行,目標是在兩個月內把整個新竹玩透透! 來到了第三個禮拜,今天我約了新竹在地人的大學朋友,請他騎機車載我到處逛逛😆 不過因為他早上有事情,所以我們就約中午吃飯。中午我們去吃城隍廟附近的 阿桂羊牛雜 ,我點了朋友很推的 羊肉炒麵 ,這家的炒麵很特別,醬汁很濃稠,沙茶味很香~ 我點加辣但有點太辣了,下次可能點小辣就好。另外有附飲料和冷氣這點很加分。 (只顧跟朋友聊天,就忘記拍照了😂) 阿桂羊牛雜 羊肉炒麵 $100 推薦指數:4⭐ 吃完飯後,本來想去南寮漁港,但因為今天的太陽真的太大了! 所以朋友就提議先去 新竹巨城 吹冷氣,晚點再去南寮漁港。雖然已經來過巨城一次,但跟別人一起逛就是不太一樣。我們去逛了服飾店、書局和湯姆熊,不知不覺就三點了。於是就離開巨城前往南寮漁港囉~ 本來以為 南寮漁港 很遠,但騎機車一下子就到了,果然在新竹還是要有機車比較方便阿! 我們先去南寮漁港的遊客中心,展望台的景色很不錯,室內還有溜滑梯可以玩呢! 接著我們在附近的魚市場、國際風箏場等地方邊聊邊走,最後走到 魚鱗天梯 。 魚鱗天梯看起來的確很像魚鱗,但聽說他的功能其實是消波塊,還真酷! 底下就有一小片沙灘,因為我今天穿拖鞋,就有下去踩一下海水。不過這裡的海水沒很乾淨,上來後腳上全都是沙子,幸好旁邊就有可以洗腳的地方。 其實旁邊有個滿有名的 17公里海岸自行車道 ,不過我們比較晚才到,所以就沒租腳踏車去騎了。 接著就往南到 香山濕地 ,騎機車也是一下就到了。 香山濕地就像小型的高美濕地,一旁的 賞蟹步道 可以直接走在溼地上方。 賞蟹步道兩旁真的很多螃蟹,照片裡的白點都是螃蟹哦! 當時剛好碰上漲潮,於是我們就在步道上拍起縮時攝影,從影片中可見漲潮的速度有多快! 香山濕地也是看夕陽的好景點,只是有點太早來了,於是我們走去旁邊的 綠色隧道 ,等待夕陽下山。 最後終於等到夕陽了! 加上倒影還滿漂亮的,只可惜今天海面有點雲,無緣看到夕陽落到海平面之下的景色。 最後順路繞去附近的 青青草原 ,雖然天色已經暗了下來,不過因此溜滑梯都不用排隊,可以多溜了幾趟😁 我們也去看了一眼大草原,但因為傍晚有一堆蚊蟲,所以就趕緊撤退了! 最後晚餐去吃 蛋包飯 ,這家也是朋友推薦的...