カロリーメイトください

Barbaroi Ware(バルバロイ・ウェア)という名前でアプリ開発してます

【Ruby】天鳳の牌譜データをRubyで取得してみる

概要

唐突ですが天鳳(オンライン麻雀ゲーム)のサイトから牌譜データを取得する方法です。

天鳳では一部のゲームの牌譜がログとして保存・公開されています。

tenhou.net

今回、Rubyでささっと過去ログを取得することができましたので書き留めておきます。

なお、スクリプトで牌譜のログを取得することも認められていますが、一部制限がありますので上記URLの記載事項に従ってください。

環境

方法

ここでは2018年の牌譜を取得してみます。
まずhttp://tenhou.net/sc/raw/の「過去ログ」より"scraw2018.zip"をDLします。

f:id:yjkym:20191202213149p:plain

適当な場所に解凍してやると大量の.gz形式のファイルが確認できます。

f:id:yjkym:20191202213528p:plain:w400

"~~~.log.gz"という形式のファイルと"~~~.html.gz"という形式のファイルがありますが、牌譜が含まれているのは"~~~.html.gz"形式のファイルのみです。

今回の目的は牌譜のログを取得することですので適当な.html.gz形式のファイルを解凍してやります。

.gzという形式の圧縮ファイルはあまり馴染みがないかもしれませんが、Windowsならたとえば「7-Zip」などのソフトで解凍することができます。

sevenzip.osdn.jp

無事に解凍ができると下のような書式のHTMLファイルを得ることができます。

f:id:yjkym:20191202214537p:plain

HTML内のリンクから実際の対局の牌譜を閲覧することができますが、データとして取得してやるにはもうひと手間必要です。

まず、牌譜を取得する対局の対局IDを取得する必要があります。

HTMLのソースコードを確認すると以下のような形式になっています。

00:00 | 07 | 三鳳南喰赤- | <a href="http://tenhou.net/0/?log=2018010100gm-00b9-0000-d826273f">牌譜</a> | 海胆トロ烏賊(+61.0) akosu(+13.0) 樽なの壊さないで(-74.0)<br>
00:02 | 28 | 四鳳南喰赤- | <a href="http://tenhou.net/0/?log=2018010100gm-00a9-0000-257139d7">牌譜</a> | まきし(本垢1)(+49.0) みっきー(+3.0) 真エトペン(-18.0) かき氷(-34.0)<br>
00:04 | 26 | 四鳳南喰赤- | <a href="http://tenhou.net/0/?log=2018010100gm-00a9-0000-993b54cb">牌譜</a> | 我妻由乃(+52.0) asada12(+5.0) いんぱち(-20.0) えりんぼP(-37.0)<br>
00:07 | 12 | 三鳳南喰赤- | <a href="http://tenhou.net/0/?log=2018010100gm-00b9-0000-26933b84">牌譜</a> | ラララコッペパン(+68.0) sigenori(-1.0) 牛肉玉子飯(-67.0)<br>
00:09 | 26 | 四鳳南喰赤- | <a href="http://tenhou.net/0/?log=2018010100gm-00a9-0000-bba65cc5">牌譜</a> | スティア(+52.0) 留チョロ(+17.0) うけながすぜ(-25.0) obama88(-44.0)<br>
00:10 | 30 | 四鳳南喰赤- | <a href="http://tenhou.net/0/?log=2018010100gm-00a9-0000-9ebd813e">牌譜</a> | CLS(+48.0) かしかお(+16.0) 水哉のレジェンド(-14.0) tori0612(-50.0)<br>
00:10 | 12 | 四鳳東喰赤- | <a href="http://tenhou.net/0/?log=2018010100gm-00e1-0000-455507c1">牌譜</a> | 今日も晴天♪(+48.0) 今日一(+7.0) みみず(-18.0) 梅さん129(-37.0)<br>
00:12 | 14 | 三鳳南喰赤- | <a href="http://tenhou.net/0/?log=2018010100gm-00b9-0000-2f883783">牌譜</a> | TIB(+56.0) 北小路(-7.0) きーぼう(-49.0)<br>
・・・・・・

aタグの中のlog=xxxxxxxxxxxxxxxxxxxxの部分が対局IDですので、この部分を正規表現を使用して抽出してやればよさそうです。

    m = line.match(/<a href="http:\/\/tenhou.net\/0\/\?log=(.+?)">牌譜<\/a>/)
    id = m[1]

たとえばこんな感じ。(可読性とか気にしてはいけない)

で、実際のログは
http://tenhou.net/0/log/?{対局ID}
のURLから取得することができます。


http://tenhou.net/0/log/?2018090100gm-00a9-0000-048fafb4

f:id:yjkym:20191202221211p:plain

これで天鳳の牌譜データのログを取得することができました。

今回はHTMLから対局IDを抽出する部分以降をスクリプト化し、最終的に取得したログを正規表現にかけて<AGARI>タグの中身(アガリ形のデータ)を表示させてみています。

require 'open-uri'

File.open("{HTMLファイル名}.html", mode = "rt:utf-8:utf-8"){|f|
  # HTMLを1行ずつ読み込む
  f.each_line{|line|
    # 対局IDを抽出する
    mtc = line.match(/<a href="http:\/\/tenhou.net\/0\/\?log=(.+?)">牌譜<\/a>/)
    id = mtc[1]

    # 生ログのURL
    get_url = "http://tenhou.net/0/log/?" + id

    open(get_url) do |file|
        html = file.read    
        # 取得したHTMLから<AGARI>タグの中身だけを表示させる
        mtcs = html.scan(/(<AGARI.+?\/>)/)
        mtcs.each do |m|
          agari_data = m
          puts agari_data
        end
    end
    # 念のため1秒待機してから次のループに入る
    sleep(1)
  }
}

出力結果

<AGARI ba="0,1" hai="12,16,22,41,43,63,65,68,78,83,86,89,93,96" machi="68" ten="30,8000,1" yaku="1,1,7,1,52,1,54,1,53,1" doraHai="91" doraHaiUra="10" who="3" fromWho="1" sc="250,0,250,-80,250,0,240,90" />
<AGARI ba="0,0" hai="45,49,52,53,57,58,59,60,76,81,85" m="22528" machi="45" ten="50,8000,1" yaku="8,1,52,1,54,2" doraHai="16,79" who="3" fromWho="1" sc="250,0,250,-80,250,0,250,80" />
<AGARI ba="0,0" hai="12,13,15,16,21,79,80,83,84,87,91" m="35135" machi="91" ten="30,2000,0" yaku="8,1,54,1" doraHai="113" who="1" fromWho="1" sc="250,-10,250,20,250,-5,250,-5" />
<AGARI ba="0,1" hai="0,2,3,80,82,84,88,92,93,98,103,124,126,127" m="31264" machi="93" ten="40,9000,2" yaku="1,1,2,1,0,1,18,1,52,1,54,1,53,0" doraHai="114" doraHaiUra="59" who="2" fromWho="2" sc="350,-60,350,-30,340,100,0,0" />
<AGARI ba="0,0" hai="38,40,45,64,66,78,83,86,132,133,135" m="49706" machi="38" ten="40,3900,0" yaku="20,1,19,1" doraHai="49" who="0" fromWho="2" sc="250,39,250,0,250,-39,250,0" />
<AGARI ba="1,3" hai="13,17,22,24,29,32,56,63,66,84,86,128,130,131" machi="24" ten="40,5200,0" yaku="1,1,2,1,19,1,53,0" doraHai="94" doraHaiUra="41" who="2" fromWho="0" sc="255,-55,255,0,225,85,235,0" />
<AGARI ba="0,1" hai="18,22,25,61,66,70,92,94" m="22967,32799" machi="25" ten="30,7700,0" yaku="6,1,24,1,52,1,54,1" doraHai="16" who="2" fromWho="3" sc="250,0,250,0,250,87,240,-77" />
<AGARI ba="0,2" hai="53,54,57,59,62,63,74,77,81,93,97,100,109,111" machi="100" ten="40,7700,0" yaku="1,1,9,1,52,1,53,0" doraHai="91" doraHaiUra="115" who="0" fromWho="1" sc="340,97,340,-77,350,0,0,0" />
<AGARI ba="0,1" hai="23,24,29,62,67,71,72,79,81,89,92,99,130,131" machi="29" ten="30,4000,0" yaku="1,1,0,1,52,1,53,0" doraHai="84" doraHaiUra="80" who="2" fromWho="2" sc="250,-20,250,-10,240,50,250,-10" />
<AGARI ba="0,0" hai="76,78,79,80,82,83,85,89,98,103,107" m="49738" machi="78" ten="30,7700,0" yaku="19,1,34,2,52,1" doraHai="99" who="2" fromWho="0" sc="350,-77,350,0,350,77,0,0" />
<AGARI ba="0,0" hai="39,42,47,99,101,104,106,107" m="48235,45579" machi="101" ten="30,7700,0" yaku="12,1,18,1,23,1,52,1" doraHai="38" who="2" fromWho="1" sc="250,0,250,-77,250,77,250,0" />
<AGARI ba="0,0" hai="4,7,18,20,25,42,47,51,84,85,86" m="60887" machi="42" ten="30,7700,0" yaku="8,1,52,3" doraHai="82" who="2" fromWho="0" sc="250,-77,250,0,250,77,250,0" />
<AGARI ba="0,0" hai="48,54,56,73,76,81,86,90,92,97,103,107,118,119" m="31008,30752" machi="73" ten="30,18000,2" yaku="7,1,24,2,52,3" doraHai="98" who="0" fromWho="1" sc="350,180,350,-180,350,0,0,0" />
<AGARI ba="0,0" hai="28,29,31,52,59,62,87,88,93,128,129" m="42571" machi="93" ten="30,7700,0" yaku="14,1,52,1,54,2" doraHai="56" who="1" fromWho="3" sc="250,0,250,77,250,0,250,-77" />
<AGARI ba="0,1" hai="5,7,9,10,11,44,45,46,59,60,65,74,79,83" machi="74" ten="40,8000,1" yaku="1,1,53,3" doraHai="115" doraHaiUra="6" who="3" fromWho="0" sc="250,-80,250,0,250,0,240,90" />

<AGARI>タグの中身の解析については別記事でやる予定です。
カロリーメイトください。

PR

そんなことを考えながら作ったアプリがこちらです
kankeli.netAndroid
https://play.google.com/store/apps/details?id=com.BarbaroiWare.MahjongScoreDrilliOS
https://apps.apple.com/jp/app/id1493166793