【反則技】タイピングが遅い僕でもRubyで自動化すればゲームで勝てるはず
最近使い始めたブラウザ自動化ツールのSelenium、なんでみんな使わないんだろうって思うぐらい便利で面白いので、このネタで他にも色々とnoteを書いていきます。
僕は毎日パソコンを使っていますがいまだにブラインドタッチ(手元を見ずにタイピングすること)ができません。
そこで本来はタイピングの練習をするべきなのですが、エンジニアらしい(?)考えとして「この作業… 自動化できそう!」というアイデアが浮かんだので実際にやってみました。
※タイピング技術の向上を目的として遊ぶタイピングゲームでタイピングを自動化しても意味がない(ゲームの目的が失われる)のは事実です。
スクレイピングを実行するプログラムを扱う際はアクセス先のサイトに不利益を与えないように注意しながら行いましょう。
今回紹介する方法は主にフロントエンド側での「表示の操作」にとどめており、自動化によって作成した成績を不正なランキング操作を目的に登録しようとするものではありません。
使うサイト
・myTyping
環境
・Windows10 Home 64bit
・WSL Ubuntu 18.04.3 LTS
・Ruby 2.4
タイピングゲーム自動化の方法
自動化するのはタイピングです。
画面上に表示されながら切り替わっていく問題を瞬間的に読み取り、自動で入力するプログラムをRubyで書いていきます。
ソースコード全体
全体と言ってもそんなに長いコードではないので解説に入る前に貼っておきます。
# gemの読み込み
require 'selenium-webdriver'
# ChromeDriverの読み込み
Selenium::WebDriver::Chrome::Service.driver_path = "../chromedriver.exe"
# Chromeの操作
d = Selenium::WebDriver.for :chrome
d.get("https://typing.twi1.me/game/18144")
d.find_element(:class, 'mtjSeSc-settingBtn').click
sleep(2)
d.find_element(:css, 'body').send_keys(:space)
sleep(2)
d.find_element(:css, 'body').send_keys(:space)
loop do
text = d.find_element(:css, '.mtjGmSc-roma .mtjNowInput').text
d.find_element(:css, 'body').send_keys(text)
end
このソースはブラウザ自動化ツールのSeleniumを使うRubyプログラムなので、実行する前に環境が整っているか確認するようにしてください。
Seleniumの環境構築については前回のnoteで詳しく解説していますのでそちらを参考にしてもらえるとありがたいです。
自動化プログラムの解説
ファイル名は「auto_typing.rb」とします。
RubyでSeleniumを動かすためのテンプレートコード3行を記述してから始めましょう。
require 'selenium-webdriver'
Selenium::WebDriver::Chrome::Service.driver_path = "../chromedriver.exe"
d = Selenium::WebDriver.for :chrome
gemとChromeDriverを読み込み、自動操作するChromeのウィンドウを取得して変数dで扱えるようになります。
マイタイピングにアクセス
タイピングゲーム(練習)サイトであるmyTypingのゲームページにアクセスするコードを書きます。
今回は同サイト内で「激ムズ」と指定されている「ワープロ検定速度練習1」のタイピングを自動化していきます。
d.get("https://typing.twi1.me/game/18144")
アクセスして開いたページでゲームを自動的にスタートさせましょう。
SeleniumでmyTypingにアクセスすると以下のような簡単な初期設定画面が表示されます。
設定はデフォルトのままでいいのですが、次の画面に進むためにOKボタンを押す必要があります。
OKボタンを表示しているHTMLは次の通り(Chromeデベロッパーツール)。
「mtjSeSc-settingBtn」というclassを持っていることが分かればその要素をクリックさせるコードを書くことで自動でOKボタンを押すことができます。
d.find_element(:class, 'mtjSeSc-settingBtn').click
OKボタンを押すと画面が切り替わりますが、まだゲームを始められません。
ゲームを開始するよう指示を出す必要があります。
OKボタンのようにスタートボタンを押すコードを書いてもいいのですが、実はmyTypingのゲームページではキーボードの特定のキーを押すことで画面上に表示されているボタンと対応した動作を行えるようになっていて、画面上のボタンよりもキーを押す方が細かいHTML構造を意識しないで済むので、対応したキーで操作が行える場合はできるだけそちらを使います。
スタートボタンはスペースキーで代替できると書いてあるので、スペースキーを押すコードを書きましょう。
d.find_element(:css, 'body').send_keys(:space)
ここでのキーボード操作は特定の要素に対してというわけではなく、表示したページ全体でアクティブになっている状態でのキーボード操作を検知するというものですので、ページの表示部分であるbodyタグ全体にスペースキーを送るようにします。
1回スペースキーを押すと上の画面が表示され、ゲームをスタートしてタイピングを始めるためにもう一度スペースキーを押す必要があります。
スペースキーを押すコードを追加しましょう。
ゲームページを開いてOKボタンを押してからここまでで2回スペースキーを押しますが、スペースキーを押す画面が表示されるタイミングに若干のズレ(遅れ)がありますので、それぞれの1行前にsleepメソッドで2秒挟んでから実行されるようにしておきます。
d.get("https://typing.twi1.me/game/18144")
d.find_element(:class, 'mtjSeSc-settingBtn').click
sleep(2)
d.find_element(:css, 'body').send_keys(:space)
sleep(2)
d.find_element(:css, 'body').send_keys(:space)
これでmyTypingのゲームページにアクセスしてタイピング画面に移ることができるようになりました。
自動タイピング
ここからが実際に自動でタイピングを行うプログラムの解説です。
まずはChromeのデベロッパーツールでタイピング時のコードの動きを確認します。
「mtjGmSc-roma」というclassの付いたdivタグの中にある「mtjNowInput」というclassの付いたspanタグによって、その時入力するべき文字が動的に出力されています。
これをCSSセレクターで表現して文字列を取得、変数textに代入します。
text = d.find_element(:css, '.mtjGmSc-roma .mtjNowInput').text
自動タイピングは、
① 入力状況に応じて動的に変化する「その時入力すべき文字」を取得
② 取得した文字列を入力
・ ①と②のステップを繰り返す
この3つをプログラミングすることで実現できます。
取得した文字列の入力はsend_keysメソッドを使い、先ほどスペースキーを押した時と同じ要領で行いましょう。
d.find_element(:css, 'body').send_keys(text)
あとは繰り返し処理を実行するloopメソッドで①と②のコードを囲めば、自動タイピングプログラムの完成です。
loop do
text = d.find_element(:css, '.mtjGmSc-roma .mtjNowInput').text
d.find_element(:css, 'body').send_keys(text)
end
結果
完成したRubyファイル「auto_typing.rb」を実行してみました。
ミス0、100%正解でスコアは10289でした。
レベルは「神」になるそうです。
続いてその下に表示されるランキングを見てみます。
僕のスコアは10289だったので2位になりますね。(ランキングには登録していません)
自動タイピングプログラムを使っても1位にはなれませんでした。
というか1位の人、打鍵/秒が29.4でミス0ってすごすぎます。
もしかしたらこの人も自動化プログラムを使っているのかもしれません(本当に達人なのかも)が、自動化プログラムのようなものを使って作成した成績をランキングに登録する行為は真面目に取り組んでいる人の迷惑になりますので、やめておきましょう。
それでは今回のnoteはここまでです。
ありがとうございました!
この記事が気に入ったらサポートをしてみませんか?