蛇ノ目の記

技術のことも。そうでないことも。

Python入門者向けハンズオン #6に向けて、という体でスクレイピングの練習をしてみた

BeautifulSoupを使って海外の歌詞サイトMetroLyricsから歌詞をスクレイピングするスクリプトを書いた。10月28日(土)に開催されるPython入門者向けハンズオン #6(#PyNyumon)でメンターをやることになっているので、その予習。

github.com

こういう感じのスクリプト(READMEと同じ内容)

  • MetroLyricsからランダムに歌詞を抽出して表示する.

  • アーティスト名を引数で指定

  • 指定されたアーティストのMetroLyricsにある全曲を対象にする

  • 日本語歌詞にも対応

  • Usage

    • $ python fetch_lyrics.py "Artist Name"
  • example

    $ python fetch_lyrics.py Oasis

    $ python fetch_lyrics.py Arctic Monkeys

    $ python fetch_lyrics.py Aimer

作ってみて気づいたことなんかを書いていきたい。

  • リダイレクトしているかどうかはrequestsでは以下の方法で判断できる
>>> url = URL
>>> r = requests.get(url)
>>> r.history

MetroLyricsでは歌詞リストのURLは http://www.metrolyrics.com/{アーティスト名}-alpage-{ページ番号}.html のフォーマットになっている。登録されている曲数に応じてページ数が変わるわけで、それ以上のページ番号を指定すると404が返ってくるという予想の元で進めていた。しかし実際はhttp://www.metrolyrics.com/{アーティスト名}-lyrics.htmlにリダイレクトする。リダイレクトしている場合、上記r.historyの戻り値は[<Response [302]>]になる。リダイレクトしていない場合は空のリストが返ってくる。

  • スクレイピングした結果が文字化けした場合は、BeautifulSoup側でデコードさせる

海外のサイトということで取得する歌詞はすべて英語であるという前提だったが、試しにAimerEGOISTと入れてみた結果、歌詞リストが存在しており歌詞が取得できた。しかし日本語歌詞は文字化けを起こしていた。

requestsオブジェクトをrとしたとき、r.textとすると文字化けが発生しやすい。このr.textではデコード済みのレスポンスボディをstr型で返している。r.contentbytes型のレスポンスボディを取得してBeautifulSoupに渡すことでBeautifulSoup側でデコードしてくれる。

スクレイピングでの文字化けを防ぐ方法の詳細は以下のブログが詳しい。Pythonクローリング&スクレイピングの著者による解説なので心強い。

orangain.hatenablog.com

#PyNyumonでは特に後者で躓く受講者がいるかもしれない。そのときに解決の手助けができたら、いいなぁと思う。

実は今回の試みは、spaCyに食わせる英語テキストが欲しくて始めた。そのspaCyのチュートリアルはしばらく放置してしまっている…。