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上,後续会持续的更新,如果喜欢也麻烦帮我按个星星吧~

有任何问题或建议,都欢迎在底下留言区提出,还请大家多多指教。


<<:  Angular 深入浅出三十天:表单与测试 Day13 - 整合测试实作 - 被保人 by Template Driven Forms

>>:  [Day 14] Reactive Programming -Reactor(COLD VS HOT) -PART 1

Day1 参加职训(机器学习与资料分析工程师培训班),记录学习内容(6/30-8/20)

人工智慧与机器学习概论 第一天,早上介绍AI相关的产业,以及目前应用的领域有哪些,例如:AIot智慧...

Day20 vue.js椅毒供毒之整理code

写出不乾净的code跟WEED一样 一开始写的时候可能会感到轻松快乐 但是後续的维护或修改会把自己搞...

JS 12 - 继承方法

大家好! 我们花了两天介绍原型链和原型继承的原理,今天就要介绍继承的方法了。 我们进入今天的主题吧!...

Day29 - 重要观念: 死结与DB transaction

上一篇中整理了一些面试中常被问到的技术问题,其中我觉得两个比较重要的就属死结(deadlock)与D...

Composite 合成模式

今天要来介绍一个比较特别、平常可能不太常见的模式。就让我们直接进入问题吧 问题 假设有间百货公司周年...