続・将棋ウォーズの棋譜をまとめて保存する方法
以前、将棋ウォーズの棋譜を 将棋ウォーズ棋譜検索β で検索してローカルに保存 という流れをやってみたが、 よく見たら2018年8月以降の棋譜が出てこなくなっていた。(私だけ?)
ということで、最近の棋譜を取得するべく、別の手法で棋譜をダウンロードしてみたいと思う。
さらに今回は、ローカルに保存するだけではなく、ローカルのデータベースに保存して棋譜を再生できるようにしてみた。 その際に必要となったセットアップなどのメモ。
成果物
データベースに棋譜を登録
最近のアップデートで戦型のタグがつくようになった。棋譜を解析しなくてもどういった内容かわかるのでとても嬉しい。
一応再生できる(必要性はない)
使用したコードは GitHub に公開している。
環境
- 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にコードを公開しているので、
- コードをダウンロード
- 以下の手順でスクリプトを実行する
$ python updateDB.py
これでMongoDBに棋譜データが閲覧できる分だけ保存される。重複して登録しないようにしてあるので、後からもう一度実行することで新しい分だけを取得できる。
対局ルールは以下の規則で命名してある。
10分切れ負け | 10m |
3分切れ負け | 3m |
10秒将棋 | 10s |
もしデータベースじゃなくてローカルにファイルとして保存したいときは、
- コードをダウンロード
- 以下の手順でスクリプトを実行する
$ python downloadKifu.py
とすれば良い。
データベースを利用する準備
MongoDB のインストール
MongoDB というオープンソースのデータベースを使ってみる。
MongoDB はJSON形式でデータを格納できるので使い勝手が良い(個人的に)
- 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というライブラリをインストールする。
- 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がある。
とても使いやすいのでこちらを使って棋譜を再生してみた。
使い方
- pip を使ってインストール
$ pip install python-shogi
- 将棋盤を描画するまで
ポイント
入出力はSFEN形式で行う.
http://ch.nicovideo.jp/kifuwarabe/blomaga/ar795371
- 駒を動かす
>>> board.push(shogi.Move.from_usi(["操作"]))
- 盤面を描画する
>>> print(board.kif_str()))
- SFEN形式の文字列を取得
>>> board.sfen()
Tips
過度なアクセスはサーバーに負荷をかけるので十分に注意しよう。 少なくとも1秒くらい間隔を開けながらアクセスする!
Raspberry Pi Camera Module V2 の使い方 (Python 3)
Raspberry pi 公式が販売しているカメラモジュール Camera Module V2 を使ってみたメモ
https://www.raspberrypi.org/products/camera-module-v2/
参考にしたもの
公式の情報
Getting started with the Camera Module - Introduction | Raspberry Pi Projects
先人の情報
PythonでRaspberry Pi カメラを制御する
【Raspberry Pi】Camera Module V2を接続する
環境
- Raspberry Pi 3 model B+
- Python 3.7.0
モジュールの準備
何はともあれ、Raspberry Pi 3 と カメラモジュールを接続します
こちらが詳しいです。向きなどに注意しましょう
次に、raspi-config > 5. Iterfacing Options > P1. Cameraからカメラを有効にしましょう
Pythonからの操作方法
picameraパッケージのインストール
% pip install --upgrade pip % pip install picamera
写真を撮影する
from picamera import PiCamera from time import sleep camera = PiCamera() camera.resolution = (800, 600) camera.start_preview() sleep(2) camera.capture("./image.jpg") camera.stop_preview()
camera.resolution(width, height)
で撮影する写真のサイズを指定camera.start_preview()
でカメラを起動(ラズパイがディスプレイに接続されていると確認できる)cmera.capture([保存したい場所])
で写真を撮影できるcamera.stop_preview()
でカメラを終了する
基本的な使い方はこれだけ。
こんな感じで撮影できましたか?
動画の録画
動画も撮影できます。
from picamera import PiCamera from time import sleep camera = PiCamera() camera.resolution = (800,600) camera.start_preview() camera.start_recording("./movie.h264") sleep(10) camera.stop_recording() camera.stop_preview()
動画も写真とほぼ同様の手順で録画できます。異なるのは、
camera.start_recording([保存する場所])
で録画開始sleep([秒数])
で何秒間録画するかを指定camera.stop_recording()
で録画停止
の部分だけ。
エフェクト
なぜか多種類のエフェクトが用意されています。ぜひ活用してみましょう。
使用できるエフェクトは以下の通りです。
>>> camera.IMAGE_EFFECTS {'none': 0, 'negative': 1, 'solarize': 2, 'sketch': 6, 'denoise': 7, 'emboss': 8, 'oilpaint': 9, 'hatch': 10, 'gpen': 11, 'pastel': 12, 'watercolor': 13, 'film': 14, 'blur': 15, 'saturation': 16, 'colorswap': 17, 'washedout': 18, 'posterise': 19, 'colorpoint': 20, 'colorbalance': 21, 'cartoon': 22, 'deinterlace1': 23, 'deinterlace2': 24}
使用する場合は次のように指定します。
camera.image_effect = "[エフェクト名]"
具体例
テキストを挿入する
以下のようにすることで、写真や動画にテキストを表示できます。
camera.annotate_text_size = [フォントサイズ] camera.annotate_text = [表示したいテキスト]
注意すること
サイズの限度
写真の場合は2592 x 1944で、動画の場合は1920 x 1080までです。
また、最大解像度での撮影を行う際は、
camera.framerate = 15
でフレームレートを15
に設定する必要があります。
ファイルフォーマット
写真のフォーマットを変更することもできます。
変更したいときは以下のように指定する。
camera.capture("[ファイルパス]", format="[フォーマット名]")
利用できるフォーマットは以下の通り。
jpeg, png, gif, bmp, yuv, rgb (24-bit RGB), rgba (32-bit RGBA), bgr (24-bit BGR), bgra (32-bit BGRA), raw
動画も同様にフォーマットを変更できます。
camera.start_recording("[ファイルパス]",format="[フォーマット名]")
利用できるフォーマットは以下の通り
h264, mjpeg, yuv (YUV420), rgb (24-bit RGB), rgba (32-bit RGBA), bgr (24-bit BGR), bgra (32-bit BGRA)
カメラを起動してからの待ち時間
公式には、カメラを起動してから最低2秒間は明るさの調整のために待てと書いてあります
試しに0秒から1秒おきに撮影してみました。
0秒時点
1秒時点
2秒時点
確かに0秒時点での写真は全体的に暗く青みがかって見えます。1秒時点と2秒時点の画像もよーく見ると違いますが、そこまで大きな違いは無さそうです。
この辺りは目的に合わせて調整しよう。
画像が180度回転していたら
今回の環境では問題なかったが、上下逆さに撮影されてしまう場合は以下のように指定することで画像を回転できます
camera.rotation = 180
とりあえず主要な機能はこんなところでしょう
詳しい内容は以下で確認できます
10. API - picamera.camera Module — Picamera 1.10 documentation
将棋ウォーズの棋譜をまとめてローカルに保存する方法
続編は以下の記事。
後から調べたら...
すでに有識者がフリーウェアを開発してくださっていたので、
Mac でもやりたいよという人限定の話になってしまった
成果物
棋譜をダウンロードするPython スクリプトを作成し、一括DLできた!
環境
Webスクレイピングの準備
selenium
今回は 将棋ウォーズ棋譜検索β で検索した結果を一括でダウンロードする方針でいく
このようにWebサイトから情報を一括でダウンロードすることを Webスクレイピングと呼び、
プログラムからブラウザを操作したいときには、selenium というソフトが使われる
今回はPython から操作したいので 以下のコマンドでパッケージを入れておく
% pip install selenium
ブラウザ
今回は Google Chrome をヘッドレスモードで使う。
ヘッドレスとは、実際にブラウザを起動して画面を描画したりしないモードと捉えておけば問題ないだろう
webスクレイピングは大量のデータにアクセスしたいので、いちいち画面を描画させると重くなってしまうのだ
(有名なヘッドレスブラウザとしてPhantomJS があったが、開発が終了してしまった)
selenium からブラウザを操作するためには、操作したいブラウザに対応するドライバが必要なので、以下からダウンロードしておく
Downloads - ChromeDriver - WebDriver for Chrome
具体的なコード
from selenium import webdriver from bs4 import BeautifulSoup import requests from tqdm import tqdm from time import sleep # 操作するブラウザの準備 option = webdriver.ChromeOptions() option.add_argument('--headless') driver = webdriver.Chrome(executable_path='./chromedriver', options=option) url = 'http://swks.sakura.ne.jp/wars/kifusearch/' u_name = '取得したいユーザ名' sleep(1) driver.get(url) driver.find_element_by_id('id_name1').send_keys(u_name) driver.find_element_by_id('searchBtn').click() # ページのソースを取得 soup = BeautifulSoup(driver.page_source, 'lxml') driver.quit() lis = soup.find_all(class_='btn1') kif = [] for i in lis: if 'kif' in i.get('href'): kif.append(i.get('href')) kif = ['http://swks.sakura.ne.jp/wars' + x[2:] for x in kif] for i in tqdm(kif): sleep(1) r = requests.get(i) r.encoding = 'Shift_JIS' f_name = i.split('/')[-1] # ユーザ名のディレクトリ以下にファイルを保存するようにしている # あらかじめディレクトリを作成しておく with open(u_name + '/' + f_name, mode='w') as f: f.write(r.text)
流れは以下の通り
Tips
実際のwebページがどのように記述されているかによってコードが変わるので、
(Chrome の場合)右クリック -> 検証 からコードを表示しながらプログラムすることになる
今回の場合、検索ボックスに 属性id_name1
、検索ボタンに属性searchBtn
が付与されていたので、
それらを検索し、文字列を入力 > 検索 という流れで結果を取得した
また、今回は 10分切れ負けに絞ったが、もし他の対局ルールでの棋譜が欲しい場合は
ラジオボタンを選択する処理が必要となる