機械学習で遊んでみたくてですね。
それに使う文章を用意するのに、手作業でコピペ出来なくもない量だったんですけど、Twitterでちょうどこの記事が流れてきたので、Webスクレイピングにトライしてみました。
Python・PHP・Perl・Bash・Rubyで簡単にWebスクレイピングする方法を解説する - paiza開発日誌
Pythonでやりましたが、5年くらい前に勉強した記憶を元に動けばいいや方針でやってるので、色々間違いあるかもしれません…。
やりたいこと
やりたかったのは、アニメロミックスというサイトに掲載されている「神谷浩史・小野大輔のDear Girl~Stories~」というラジオ番組の企画で配信された着ボイス(Dear Voice)の一覧を取得することです。
趣味に走った題材です(笑)
方針
現状、アニメロのサイトにはDear Voiceだけがまとまっているページはないので、神谷さん、小野さんそれぞれのアーティストページの「ボイス」カテゴリの中から、番組名「神谷浩史・小野大輔のDear Girl~Stories~」が表示されているものだけを抽出します。
実装
主にこちらのページ参考にさせていただきました。
PythonとBeautiful Soupでスクレイピング - Qiita
PythonでWebスクレイピング - imoniの開発Blog
PaizaCloud のJupyter Notebook使いました。(最近Pythonを使ってる環境がそこだったので)
import
import requests
from bs4 import BeautifulSoup
from time import sleep
requests
はWeb上のページを取得するのに必要と理解してます。
BeautifulSoup
は、標準のHTMLParserだけでやるには難しい条件で要素を探したかったので。
sleep
は、瞬間的に大量のリクエストを投げて負荷をかけるのを避けるため、待ち時間を入れるのに使いたくて。
対象となるページ
URL_C = "https://pc.animelo.....188/genre:voice" # 神谷浩史のボイス1ページ目
URL_D = "https://pc.animelo.....032/genre:voice" # 小野大輔のボイス1ページ目
1ページ目のURLがこんな感じで、
2ページ目になると https://pc.animelo.....188/genre:voice/page:2
みたいに末尾にページ数が付加される挙動でした。
(手動でアクセスすると1ページ目のURLにはページ数が出ませんが、page:1と入れてもアクセスできました。)
取得したいテキストの周りはこんな感じの構造になってまして
<div class="detail">
<p class="title">
<a href="/portals/product/xxxxxx">ここに取得したいテキストがある</a>
</p>
<p class="sub-title">...</p>
<p class="contnt-type">...</p>
<p class="description">
「神谷浩史・小野大輔のDear Girl~Stories~」
</p>
</div>
class="detail"
となっている要素をすべて探す(list的な感じで取得される)- 取得した
class="detail"
の要素に対し、class="description"
のテキストが神谷浩史・小野大輔のDear Girl~Stories~
を含むかどうかをチェック - 含むなら最初の `a` タグのテキストを出力
- 取得した
という感じでやってみました。
関数を作成
def get_voices(initial_url):
num = 1 # スタートするページ数
while num <= 30: # 無限ループしないように最大30ページに制限
url = initial_url + "/page:" + str(num) # ページ数付きのURLを作成
num = num + 1 # ページ数を増やす(次のページ数)
print(url) # 後から情報を精査したかったのでページごとにURLも出力
# 指定のURLの情報を取得して、BeautifulSoupで扱えるようにする
HTML = requests.get(url)
SOUP = BeautifulSoup(HTML.content, "html.parser")
# 「配信コンテンツは見つかりませんでした」のメッセージが
# 表示されていたら最後のページ(を超えた)と判断。whileループを終了する。
if SOUP.find(class_="product-list-not-found") is not None:
print("---取得終了---")
break
else:
# class="detail" の要素をすべて取得
res_set = SOUP.find_all(class_="detail")
# 取得したclass="detail"の要素ひとつずつに対して実行
for res in res_set:
# class="description" の要素を取得
# ここが「神谷浩史・小野大輔のDear Girl~Stories~」ならDear Voice
desc = res.find(class_="description")
if desc is None:
# 画面右に表示されるタイアップ情報の欄もclass="detail"になっていたので、
# descriptionが見つからないときはこれ以降の処理は飛ばして次のforループへ
# (たぶんタイアップ情報が最後に来るんだけど一応)
continue
# Dear Voiceの場合のみ出力する
if "神谷浩史・小野大輔のDear Girl~Stories~" in desc.string:
# 最初のaタグにボイスの文言が入っているのでそれを出力する
voice = res.find("a")
print(voice.string) # 出力
# forループここまで
sleep(3) # 瞬間的に大量にアクセスして迷惑かけないように待ち時間を…
# whileループここまで
呼び出し
# 神谷さんのボイス一覧を取得
print("===神谷さん===")
get_voices(URL_C)
# 小野さんのボイス一覧を取得
print("===小野さん===")
get_voices(URL_D)
結果
こんな感じで出力されます。
補足:
アニメロの利用規約ではスクレイピング自体は禁止されてないようですが、「サービスの内容」の「再利用」はNGとのこと。
商品そのもの(Dear Voiceなら音声)を再利用するわけではなくて、誰でも見れる商品ラインナップを分析して楽しむだけなので大丈夫かなと思ってやっておりますが…
コード学習目的で公開しておりますが、アニメロさんにご迷惑をかけることの無いようご配慮いただけますと幸いです。
0 件のコメント:
コメントを投稿