株ドラゴンの年初来安値からの値上がり率ランキングに大化け銘柄がある
ウルフ村田いわく、株ドラゴンの年初来安値からの値上がり率ランキングを毎日チェックしておくと、その中に大化け銘柄、スター銘柄が存在しているとのことです。
ただ、毎日ページ見ていても中々新しい銘柄が登場したことに気づきません。あと、ページ数が多いので、毎晩ポチポチとクリックしてページを遷移していくのが面倒だと思い、代わりにプログラミングで一発で可視化できるようにしてみようと思いました。
株ドラゴンの年初来安値からの値上がり率ランキングページをスクレイピング
robots.txtの確認
最初に株ドラゴンのページをスクレイピングしてよいのかどうか念の為確認します。
トップページの最後に/robots.txtと追記してページに飛びます。すると以下のように表示されました(2019.5.19現在)
User-agent: Mediapartners-Google
Disallow:
User-Agent: Baiduspider
Disallow: /
#China Baidu : www.baidu.com, www.baidu.jp
User-agent: ICC-Crawler
Disallow: /
User-agent: Yeti
Disallow: /
#Korea Naver : www.naver.com 29/Mar/2007~
User-agent: NaverBot
Disallow: /
#Korea Naver : www.naver.com ~26/Mar/2007?
User-agent: msnbot
Crawl-delay: 120
Disallow: /company
User-Agent: MJ12bot
Crawl-Delay: 120
User-agent: SemrushBot
Disallow: /
#170525 add
User-Agent: *
Disallow: /kabuka/
Disallow: /cgi-bin/
Disallow: /chart/
Disallow: /chart2/
Disallow: /js/
Disallow: /ranking/2001
Disallow: /ranking/2002
Disallow: /ranking/2003
Disallow: /ranking/2004
Disallow: /ranking/2005
Disallow: /ranking/2006
Disallow: /ranking/2007
Disallow: /ranking/2008
Disallow: /ranking/2009
Disallow: /ranking/201
Disallow: /ranking/202
Disallow: /top/200
Disallow: /top/201
Disallow: /top/202
Disallow: /company
Sitemap: https://www.kabudragon.com/sitemap.xml
Disallowのところに書かれているのが検索してはいけないフォルダになるので、どうやら2009年くらいまでのランキングはアクセスするなと言っています。
robots.txtの見方をご存じない方はこちらで確認してください。https://www.howtonote.jp/google-search-console/robots-txt/index1.html
201、202というフォルダが書かれていますが、2010年以降のフォルダもだめということでしょうか??それならちゃんと「2010」と書いてほしいものです。
まあ、2010年以降のrankingは明示的にだめと言われていないですし、1日1回実行できれば良いのでそれほど負荷はかからないかなということでスクレイピングしていきましょう。でも、あまり大量にアクセスしないように心がけます。
BeautifulSoupでスクレイピング
スクレイピングのモジュールはいくつかありますが、株ドラゴンのページは割と静的なページなので、BeautifulSoupでやりたいと思います。
各ページの情報をデータフレーム化
まずは、各ページのランキングのテーブルをpandasのデータフレームに変えます。
とりあえずコードをざっと示します。
# -*- coding: utf-8 -*-
# ライブラリのインポート
import requests
from datetime import datetime, timedelta
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 各ページのランキング表をデータフレーム化する関数
def get_table(url):
soup = BeautifulSoup(requests.get(url).text, "lxml")
if len(soup.body.find_all('tr')) > 20:
start_line = [i for i in range(14,20) if soup.body.find_all('tr')[i].text.splitlines()[1] == '順位']
items = [v.text.splitlines() for i, v in enumerate(soup.body.find_all('tr')) if i > start_line[0]]
cols = ['', '順位','コード', '名称', '市場','日付','終値','前日比(円)','前日比(%)','値上がり','出来高','高値','安値']
df = pd.DataFrame(np.array(items[0]).reshape(1,-1),columns=cols)
print(items[0])
for i in range(1,200):
df_add = pd.DataFrame(np.array(items[i]).reshape(1,-1),columns=cols)
df = pd.concat([df, df_add],axis = 0)
df['値上がり率(円)'] = [v.split('+')[1] for v in df['値上がり']]
df['値上がり率(%)'] = [v.split('+')[-1] for v in df['値上がり']]
df = df.drop('値上がり', axis = 1)
return df,True
else:
print('休場')
return np.nan, False
# ランキングの推移を可視化したい日付(開始と終わり)を設定
date = '2019/01/01'
end_date = '2019/05/19'
dfs = []
dates = []
while date != end_date:
strp_date = datetime.strptime(date, '%Y/%m/%d') + timedelta(days = 1)
date = datetime.strftime(strp_date, '%Y/%m/%d' )
print(date)
url = 'https://www.kabudragon.com/ranking/{}/yl_age200.html'.format(date)
df, flg = get_table(url)
if flg:
dfs.append(df)
dates.append(strp_date)
株ドラゴンの年初来安値からの値上がり率ランキングのページは、1ページに最大200銘柄表示されます。get_table関数は各ページのランキング表をpandasのデータフレームに変換する関数になります。
28, 29行目に自分が可視化したいランキング推移の期間を設定します。ここでは、2019年1月1日〜2019年5月19日が設定されています。
while文で、自分が設定した期間分の日付を1日ずつ繰り返しページを取得しているのですが、市場が休みの日はデータがありません。そのあたりのif文がget_table関数内に入っています。
上記を実行すると下のような実行結果が順々に現れると思います。
2019/01/02
休場
2019/01/03
休場
2019/01/04
['', '1', '3906', 'ALBERT', '東マ', '1/4(金)', '12,000', '-200', '-1.64%', '+10,800+900.00%', '419,800', '12,250', '11,500']
2019/01/05
休場
2019/01/06
休場
2019/01/07
['', '1', '3906', 'ALBERT', '東マ', '1/7(月)', '12,380', '+380', '+3.17%', '+11,180+931.67%', '337,200', '12,720', '12,260']
2019/01/08
['', '1', '3906', 'ALBERT', '東マ', '1/8(火)', '12,310', '-70', '-0.57%', '+11,110+925.83%', '267,100', '12,790', '12,310']
2019/01/09
['', '1', '3906', 'ALBERT', '東マ', '1/9(水)', '11,220', '-1,090', '-8.85%', '+10,020+835.00%', '520,500', '12,550', '11,100']
2019/01/10
['', '1', '3906', 'ALBERT', '東マ', '1/10(木)', '10,400', '-820', '-7.31%', '+9,200+766.67%', '559,900', '11,560', '10,250']
2019/01/11
['', '1', '3906', 'ALBERT', '東マ', '1/11(金)', '10,480', '+80', '+0.77%', '+9,280+773.33%', '787,300', '11,270', '10,160']
2019/01/12
休場
2019/01/13
休場
2019/01/14
休場
ランキング推移可視化
それでは銘柄毎にランキングの推移を可視化します。
先程同様とりあえずコードをざっと下に示します。
# 対象期間でランキングに入った銘柄コードの辞書作成
dic = {}
for df in dfs:
keys = df['コード']
values = df['名称']
buf = dict(zip(keys, values))
dic.update(buf)
# ランキング推移可視化
for k, v in dic.items():
code = k
name = v
rankings = []
close = []
day_inc_rate = []
volume = []
inc_rate = []
for df in dfs:
if len(df[df['コード'] == code]['順位']) != 1:
rankings.append(-201)
close.append(-1)
day_inc_rate.append(-100)
volume.append(-1)
inc_rate.append(-1)
else:
rankings.append(int(df[df['コード'] == code]['順位'].values[0])*-1)
close.append(float(df[df['コード'] == code]['終値'].values[0].replace(',', '')))
day_inc_rate.append(float(df[df['コード'] == code]['前日比(%)'].values[0].replace('%', '')))
volume.append(float(df[df['コード'] == code]['出来高'].values[0].replace(',', '')))
inc_rate.append(float(df[df['コード'] == code]['値上がり率(%)'].values[0].replace('%', '')))
fig, ax1 = plt.subplots(figsize =(20,3))
ax1.plot(dates, rankings,'o-')
ax2 = ax1.twinx()
# ax2.plot(np.arange(len(rankings)), close,'o-')
# ax2.plot(np.arange(len(rankings)), day_inc_rate,'o-')
# ax2.plot(np.arange(len(rankings)), volume,'o-')
ax2.plot(dates, inc_rate,'o-',color = 'orange')
plt.title([code, name])
ax1.set_ylim(-201,0)
ax2.set_ylim(0,1000)
plt.show()
出力結果はこんな感じです。


前半は銘柄名と銘柄コードを辞書化しています。その後、銘柄毎に青色の折れ線グラフでプロットしていきます。
ランキングが上位ほど上に表示されるようにしたかったので、縦軸は-201〜0に設定しています。-1が1位という意味ですね。
同時に値上がり率も一緒にオレンジ色でプロットしています。
37, 38, 39行目はコメントアウトで表示されないようにしていますが、#を外せばそれぞれ「終値」「前日比」「出来高」を同時にプロットすることもできます。
出力結果は、前半は過去にランキング上位で消えていった銘柄あるいはランキング上位でプロットが上に張り付いている銘柄が表示されます。
後半に表示される銘柄をみると、つい最近ランキング入りしてきたということがわかります。
最近ランクインしてきた銘柄を注視していこうという感じです。
おすすめ書籍
私がスクレイピングで参考にした書籍はこちらになります。
もっと勉強したいという方は参考にしていただければと思います。