at backyard

Color my life with the chaos of trouble.

sigur rósのライブのセットリストの推移をPythonを使って調べてみる

世界中のライブのセットリストをまとめたサイトがあるらしい。
ちょっと前の記事だけど、詳しくはLifehackerにて。

www.lifehacker.jp


これを使えば、Sigur Rosの最近のライブセットリストを調査して、今年のフジロックの曲目をある程度予測することが出来たのではないだろうか?と考えた。
勿論そんなことするなんて、なんて野暮なことだと一部のリスナーは言うかもしれない。
だが、こういう課題を通じて、自身のスキルを少しでも鍛えられたらという気持ちがある。
実際にデータを集計することで、どれほどの予測が可能なのか体験してみたいという気持ちもある。

というわけで、勉強がてら、ライブセットリスト予測を行ってみたいと思う。
ま、既にライブは終わっているので、あまり意味はありませんが、実際に予測があたっているかの答え合わせはすぐ出来る。

※ちなみにFuji RockSigur Ros公演前に一度彼らが今まで演奏してきた曲の集計を行ってみた。
今回の記事はその時にWEBスクレイピングしたデータを元に、分析を行っている。

なお、その時のツイートはこちら。Instagram経由でつぶやいているため、140文字目以降の文字が切れている。


なお、もっとスマートなやり方があるよ、というご意見があればコメント欄にいただけると幸いです。

サイトの使い方

というわけで、データをWEBスクレイピングで集めるところから書いていくことにする。
まずはサイトの使い方から。

setlist.fmにアクセスする。

www.setlist.fm

サイトの使い方はとても簡単です。

f:id:shinshin86:20160629060306p:plain

これで検索すれば、Sigur Rosの最近のライブのセットリスト一覧が出てくる。

検索結果はこんな感じ。

f:id:shinshin86:20160629060504p:plain

f:id:shinshin86:20160629061127p:plain


簡単で見やすいですね。


データ収集

PythonでWebスクレイピングをしてデータを収集するスクリプトを書いていく。
下記のスクリプトSigur RosのセットリストページのURLを取ってきて、更にその先の曲目リストのみをテキストで抜いてくる。
※これを行う際は適度にsleep処理を挟むなどして、スクレイピング先のサーバに負荷をかけないように気をつけてください。

crawl.py
# -*- coding: utf-8 -*-

import urllib.request
import re
import crsetlist
from time import sleep
from bs4 import BeautifulSoup


# parse url link
def fetch_url(soup, regex_url):
    m = re.search(regex_url, str(soup))
    url = m.group()
    print("Indexing %s" % url)
    return url


# get a url list
def crawl_setlist_url(page, depth=1):
    # set regex
    r_href = re.compile("setlist/sigur-ros/")
    r_url = re.compile("setlist/sigur-ros/.*\\.html")
    url_list = []
    try:
        c = urllib.request.urlopen(page)
    except:
        print("Could not open %s" % page)

    soup = BeautifulSoup(c.read(), "lxml")
    result_list = soup.find_all("a", href=r_href)
    for r in result_list:
        url_list.append(fetch_url(r, r_url))

    url_pages = ""
    for i in url_list:
        url_pages += i + "\n"

    sleep(1)
    print("Get a page list!!")

    return url_pages

if __name__ == '__main__':
    for i in range(57):
        page = "http://www.setlist.fm/search?page=" + str(i + 1) + "&query=Sigur+Ros"
        crsetlist.crawl_setlist(crawl_setlist_url(page))
        sleep(1)
crsetlist.py
# -*- coding: utf-8 -*-

import urllib.request
from time import sleep
from bs4 import BeautifulSoup


def get_setlist(page):
    result_text = ""
    # get a play's year
    year = page[18:22:]
    try:
        c = urllib.request.urlopen("http://www.setlist.fm/" + str(page))
    except:
        print("Could not open %s" % page)

    soup = BeautifulSoup(c.read(), "lxml")
    for t in soup.find_all(class_="songLabel"):
        text = t.get_text()
        result_text += str(year) + "," + text + "\n"
    return result_text


def crawl_setlist(setlist_url):
    with open('result/Setlist.csv', mode='a', encoding='utf-8') as result_file:
        for i in setlist_url.splitlines():
            result_file.write(get_setlist(i))
    sleep(1)
    print("Get a set list!! and write a text file!!")

これで

ライブを行った年,ライブで演奏した曲

という構成のcsvファイルが生成される。

※なお、crawl.pyの"for i in range(57):"の箇所は決め打ちで書いてしまっている。。。

自身のコードはPython のコーディング規約 PEP8 に準拠しているのか?

qiita.com



ちなみに自身のPythonコードをこのブログに載せる前に、自分のコードってなんだか汚すぎないか??と思い、上記の記事を参考にコードのチェックを行った。
ある程度時間をかけずにさくっと処理を書くことが目的とはいえ、まるで中途半端に墨汁を吸わせた筆で一筆書きをしたみたいに、何もかもが中途半端なコードだったのだ。。。というかまだ今も



なんだか長くなりそうなので、2つに分けて投稿しようと思う
一旦ここで切ります。