趣味プログラマーの作業メモのような投稿になりますので、ご注意ください。間違いや指摘は大歓迎です。
きっかけ
-
M-1グランプリの準々決勝に知人のガーベラガーデンが進出したのでM-1について調べたくなった
(動画配信されたようなので宣伝。https://gyao.yahoo.co.jp/player/11185/v00046/v0000000000000001148/) -
Jupyter Notebookを自宅の外でも使いたいニーズをGoogleColaboratoryで満たせることを知った
-
WEBスクレイピングに興味があった
GoogleColaboratory
開いたらJupyterLikeでした。ショートカットキーなどは違いますが習熟すればよいです。
https://colab.research.google.com/
注意点としては、特定の時間が経過するとインスタンスリセットになるので、作業結果をちゃんと定期的に保管しておかないといけません。
(参考記事:https://qiita.com/ku_don/items/2770df602dd7778d4ce6)
スクレイピング
ちゃんとルールを守ってスクレイピングしましょうということで、Robot.txtを確認。
最初の一行目で、その場でパッケージインストールしてくれてます。
(参考:https://vaaaaaanquish.hatenablog.com/entry/2017/12/01/064227)
!pip install robotexclusionrulesparser
import robotexclusionrulesparser
rerp = robotexclusionrulesparser.RobotExclusionRulesParser()
rerp.fetch('https://www.google.com/robots.txt')
if rerp.is_allowed('*', '/search'):
print("OK")
else:
print("NG")
最初はWEBページでDOM使って要素を抽出しようかと思いましたが、JSONファイルでコンビごとにデータを持ってきているWEBページを内容を生成していましたので、JSONファイルをそのままお借りすることにしました。
また、大量アクセスで迷惑をかけちゃいけないお作法として、1秒1アクセスで300アクセス毎にGoogleDriveにJSONデータを保管していきました。
import requests
def getJson(num):
url = 'https://www.m-1gp.com/combi/json/' + str(num) + '.json'
json_data = requests.get(url)
# 200以外のStatusコードで判別しようとしたが、全部200だった
#if json_data.status_code==200:
# return json_data.json()
#else:
# print(json_data.status_code)
try:
return json_data.json()
except:
return None
data = {}
import json
import time
!pip install -U -q PyDrive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials
file_id = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
for num in range(len(data)+1, 9600):
j = getJson(num)
if j is not None:
data.update({str(num): j})
else:
print("error id: " + str(num))
if num % 300 == 0:
print(len(data))
auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)
upload_file_1 = drive.CreateFile({'id': file_id})
upload_file_1.SetContentString(json.dumps(data))
upload_file_1.Upload()
time.sleep(1)
だいたい一度ぐらいインスタンスリセットされるのので、読み込む箇所も作っておきます
file_id = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
drive_file = drive.CreateFile({'id': file_id})
import json
json_dict = json.loads(drive_file.GetContentString())
data =json_dict
matplotlab
あとはローカルJupyterのときと同様に、日本語フォントを準備して描いていけば完成です。
!apt-get -y install fonts-ipafont-gothic
import matplotlib.font_manager as fm
fm.findSystemFonts()
import matplotlib
matplotlib.get_cachedir()
!rm /root/.cache/matplotlib/fontList.json
%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'IPAPGothic' #全体のフォントを設定
plt.rcParams["figure.figsize"] = [20, 12]
plt.rcParams['font.size'] = 20 #フォントサイズを設定 default : 12
plt.rcParams['xtick.labelsize'] = 15 # 横軸のフォントサイズ
plt.rcParams['ytick.labelsize'] = 15
list = []
for key, value in json_dict.items():
try:
if 'belong' in value and 'entrant' in value:
if '2018' in value['entrant']:
list.append(value['belong'])other_val = sum(df[df['count']<15]['count'])
df_t = df[df['count']>=15]
df_t = df_t.append({'所属': 'その他', 'count':other_val}, ignore_index=True)
df_t['count'].plot(kind='pie', startangle=90, counterclock=False, autopct='%.2f', labels=df_t['所属'].tolist(), figsize=(10, 10), title='2018年参加者')
except:
print(key)
import collections
c = collections.Counter(list)
df = pd.DataFrame.from_dict(c, orient='index').reset_index()
df = df.rename(columns={'index':'所属', 0:'count'})
df = df.sort_values('count', ascending=False)
other_val = sum(df[df['count']<15]['count'])
df_t = df[df['count']>=15]
df_t = df_t.append({'所属': 'その他', 'count':other_val}, ignore_index=True)
df_t['count'].plot(kind='pie', startangle=90, counterclock=False, autopct='%.2f', labels=df_t['所属'].tolist(), figsize=(10, 10), title='2018年参加者')
ほかにも、9人のお笑いグループがいることがわかったりして、なかなかしばらくいじくれそうです。