続・将棋ウォーズの棋譜をまとめて保存する方法

以前、将棋ウォーズの棋譜将棋ウォーズ棋譜検索β で検索してローカルに保存 という流れをやってみたが、 よく見たら2018年8月以降の棋譜が出てこなくなっていた。(私だけ?)

ということで、最近の棋譜を取得するべく、別の手法で棋譜をダウンロードしてみたいと思う。

さらに今回は、ローカルに保存するだけではなく、ローカルのデータベースに保存して棋譜を再生できるようにしてみた。 その際に必要となったセットアップなどのメモ。

成果物

データベースに棋譜を登録

最近のアップデートで戦型のタグがつくようになった。棋譜を解析しなくてもどういった内容かわかるのでとても嬉しい。

f:id:teriyaki398:20181110174918p:plain:w550

一応再生できる(必要性はない) f:id:teriyaki398:20181110174707g:plain

使用したコードは GitHub に公開している。

github.com

環境

  • macOS 10.14
  • anaconda3-5.0.0
  • MongoDB 4.0.3

棋譜のダウンロード

基本的な方針は前回とほぼ変わらないが、今回は公式のサイトから収集する。

https://shogiwars.heroz.jp/users/history/ユーザーID/web_app?locale=ja

アクセスすると分かるが、対局履歴を一ヶ月分(?)くらい閲覧することができる。

このページから棋譜のURLを取得してく。具体的にはgame_replayクラスの中にあるaタグにリンクが貼ってある。

特定のページにアクセスしたい時は以下のようなパラメータを設定する。

params = {
    "page" : ページ番号(一番最初のページは page = 1)
    "gtype" : 対局ルール(3切れは"sb"、10秒将棋は"s1")
}

とりあえずデータベースに登録したい時は GitHubにコードを公開しているので、

  1. コードをダウンロード
  2. 以下の手順でスクリプトを実行する
$ python updateDB.py

これでMongoDBに棋譜データが閲覧できる分だけ保存される。重複して登録しないようにしてあるので、後からもう一度実行することで新しい分だけを取得できる。

対局ルールは以下の規則で命名してある。

10分切れ負け 10m
3分切れ負け 3m
10秒将棋 10s

もしデータベースじゃなくてローカルにファイルとして保存したいときは、

  1. コードをダウンロード
  2. 以下の手順でスクリプトを実行する
$ python downloadKifu.py

とすれば良い。

データベースを利用する準備

MongoDB のインストール

MongoDB というオープンソースのデータベースを使ってみる。

MongoDB はJSON形式でデータを格納できるので使い勝手が良い(個人的に)

  1. homebrew を使ってインストール
$ brew install mongodb
  • mongodb の起動
$ brew services start mongodb
  • 起動しているかどうかの確認
$ brew services list
  • mongodb の停止
$ brew services stop mongodb
  • 特定のコレクションに含まれているデータを全て表示する
$ mongo
> show dbs
> use [db name]
> show collections
> db.[collection name].find()
コマンド 操作
mongo mongoDB のシェルを起動
show dbs データベース一覧を表示
use [name] 使用するデータベースを変更
show collections コレクション一覧を表示
db.test_collection.find() コレクションに登録されている内容を全て表示

pymongo のインストール

今回はPython 経由でデータを追加・参照する予定なので、PyMongoというライブラリをインストールする。

  1. pip を使ってインストール
pip install pymongodb
  • mongoDBへのアクセス
>>> from pymongo import MongoClient
>>> client = MongoClient("localhost", 27017)
  • データベースを使用(なければ作成)
>>> db = client["db_name"]
  • コレクションを使用(なければ作成)
>>> collection = db["collection_name"]
  • コレクションに追加
>>> type(post)
<class 'dict'>
>>> collection.insert_one(post)

複数追加したい場合は,辞書のリストを作成し,

>>> type(post)
<class 'list'>
>>> collection.insert_many(post)
  • コレクションを参照

全て取ってくる

>>> collection.find()

Cursor というイテレータオブジェクトが返ってくる. for文などで回すことで一つずつ参照できる.

一つ取ってくる

>>> collection.find_one({"key": "000"})

引数として渡した条件に一致するデータが返ってくる。

上での例でいうと、"key" が "000" のデータで一番最初に見つかったやつが返ってくる。

棋譜を再生する

Python の将棋ライブラリとしてpython-shogiがある。

とても使いやすいのでこちらを使って棋譜を再生してみた。

使い方

  1. pip を使ってインストール
$ pip install python-shogi
  • 将棋盤を描画するまで

f:id:teriyaki398:20181110183852p:plain:w550

ポイント
入出力はSFEN形式で行う.
http://ch.nicovideo.jp/kifuwarabe/blomaga/ar795371

  • 駒を動かす
>>> board.push(shogi.Move.from_usi(["操作"]))
  • 盤面を描画する
>>> print(board.kif_str()))
  • SFEN形式の文字列を取得
>>> board.sfen()

Tips

過度なアクセスはサーバーに負荷をかけるので十分に注意しよう。 少なくとも1秒くらい間隔を開けながらアクセスする!