WebDriver APIを使ってWebブラウザーを自動操作できるLuaのライブラリーを開発しました。LuaWebDriverといいます。 これは、クリアコードが株式会社セナネットワークス様からの発注を受けて開発したライブラリーです。MITライセンスで公開しています。
LuaWebDriverではWebDriver APIを使って、LuaからWebブラウザーを操作することができます。Webブラウザーはデフォルトでヘッドレスモードで起動します。(GUIでの起動もできます。)
Webブラウザーを利用してWebサイトをレンダリングするため、JavaScriptを使用して動的に生成されるWebページをスクレイピングすることや、HTMLのパーサーライブラリ等で解釈できないような正しくないHTMLで書かれたWebページのスクレイピング等に使用できます。(正しくないHTMLで書かれたWebページもWebブラウザーはなんとか表示するため。) また、Webブラウザーを操作できるので、ログインが必要なページに対して、ログインし、ログイン後のWebページをスクレイピングするようなこともできます。
対応環境
本記事執筆時点でのLuaWebDriverの対応OSと対応Webブラウザーは以下の通りです。
- 対応OS
- CentOS 7
- macOS
- 対応Webブラウザー
- Mozilla Firefox
上記以外のOS(Windows)、上記以外のWebブラウザー(Google Chromeなど)には未対応となっています。 他の環境でも使えるように改良していただけた場合には、開発プロジェクトへマージリクエストをいただけましたら幸いです。
インストール方法
LuaWebDriverは、LuaRocksで公開しており、luarocks
コマンドを使ってインストールできます。
また、Firefoxを操作するためにgeckodriverを使っているため、本ライブラリーの他にgeckodriverのインストールも必要です。
例えば、CentOS 7では、以下のようにインストールします。
% yum install -y gcc gcc-c++ firefox lua-devel luajit-devel luarocks make openssl-devel
% curl -L -O https://github.com/mozilla/geckodriver/releases/download/v0.23.0/geckodriver-v0.23.0-linux64.tar.gz
% tar xf geckodriver-v0.23.0-linux64.tar.gz -C /usr/local/bin
% chmod +x /usr/local/bin/geckodriver
% sudo luarocks install web-driver
CentOS 7以外のインストール方法は、LuaWebDriverのドキュメントのインストールを参照してください。
基本的な使い方
LuaWebDriverを使ってFirefoxを操作するには、web-driver.Firefox
クラスのオブジェクトが必要です。
web-driver.Firefox
クラスのオブジェクトは以下のように作成します。
local Firefox = require("web-driver/firefox")
local firefox = Firefox.new()
web-driver.Firefox
クラスのオブジェクト作成時には、様々なオプションが設定できますが、ここでは、わかりやすさのため、オプションは設定せず、全てデフォルト値で実行します。
設定可能なオプションについては、web-driver.Firefox
クラスのリファレンスを参照してください。
web-driver.Firefox
クラスのオブジェクトを作成しました。次は、作成したオブジェクトを使って、Firefoxを起動し、操作します。
Firefoxの起動と操作は、web-driver.Firefox:start_session()
を使って行います。
web-driver.Firefox:start_session()
は引数にコールバック関数を指定でき、LuaWebDriverは、Firefox起動後、引数に指定されたコールバック関数を実行します。このweb-driver.Firefox:start_session()
の引数に与えるコールバック関数内にFirefoxを操作して実行したい処理を実装します。
例えば、指定したURLのWebサイトへアクセスする場合は以下のように実装します。
local Firefox = require("web-driver/firefox")
local firefox = Firefox.new()
local URL = "https://clear-code.gitlab.io/lua-web-driver/sample/"
-- コールバックの作成とセッションの開始
firefox:start_session(function(session)
-- 指定したURLのWebサイトへアクセス
session:navigate_to(URL)
end)
コールバック関数の引数には、起動したFirefoxとのセッションがweb-driver.Session
クラスのオブジェクトとして渡されます。
このオブジェクトを使って、ブラウザーの操作を実装します。
Webサイトへのアクセスは、web-driver.Session:navigate_to()
を使って行います。このメソッドの引数にアクセスしたいWebサイトのURLを指定すると、そのURLへアクセスできます。
Webサイトへのアクセス以外の操作については、web-driver.Session
クラスのリファレンスに記載がありますので、合わせて参照してください。
主な機能
LuaWebDriverの主な機能を紹介します。 LuaWebDriverを使うとLuaで以下のようなことができます。
Webサイトへのログイン、ページ内のリンククリック
ここでは、ログインが必要なWebサイトへアクセスし、ログインを実施、ログイン後のページ内のリンクをクリックしてWebページを移動、移動後のページの要素のテキストを取得する例を示します。 少し複雑な例ですが、Webサイトの操作によく使う機能を紹介できるので、このような例にしました。
ログインの実行やリンククリックを行うには、特定のフォームへのテキスト入力、ボタン操作、リンクのクリック操作が必要です。
LuaWebDriverでは、これらを、web-driver.Session:css_select
とweb-driver.ElementSet:send_keys()
、web-driver.ElementSet:click()
、web-driver.Session:link_search()
というメソッドで実現します。
具体的な使い方は、以下の実装例を使って説明します。
local Firefox = require("web-driver/firefox")
local firefox = Firefox.new()
local URL =
"https://clear-code.gitlab.io/lua-web-driver/sample/move.html"
-- コールバックの作成とセッションの開始
firefox:start_session(function(session)
-- ログインが必要なページへアクセス
session:navigate_to(URL)
-- Webサイト内のフォームを取得
local form = session:css_select('form')
-- ユーザー名を入力するためのフォームを取得
local text_form = form:css_select('input[name=username]')
-- フォームにユーザー名を入力
text_form:send_keys("username")
-- パスワードを入力するためのフォームを取得
local password_form = form:css_select('input[name=password]')
-- フォームにパスワードを入力
password_form:send_keys("password")
-- ユーザー名とパスワードを送信するためのボタンを取得
local button = form:css_select("input[type=submit]")
-- ユーザー名とパスワードを送信
button:click()
-- リンク操作をするための要素オブジェクトを取得
local link = session:link_search("1")
-- リンクをクリック
link:click()
local elements = session:css_select("p")
-- 取得した要素のテキストを取得
print(elements:text())
-- 1
end)
ログイン
まずは、web-driver.Session:css_select()
を使って、ユーザー名を入力するフォームを取得します。 web-driver.Session:css_select()
は、CSSセレクターを用いて取得したい要素を指定できます。上記例では、input[name=username]
としているので、name属性がusernameとなっているinput要素を取得します。
取得した結果は、web-driver:ElementSet
クラスのオブジェクトとして返ってきます。
返ってきたオブジェクトを使って、web-driver:ElementSet:send_keys()
を実行します。このメソッドは、取得した要素に対して指定したテキストを入力します。上記例では、取得したinput要素にusernameという文字列を入力しています。
これで、ユーザー名の入力は完了です。
次にパスワードの入力を実施します。パスワードの入力もユーザー名の入力と同様web-driver.Session:css_select()
を使ってinput要素を取得し、取得したinput要素に対して、web-driver.ElementSet:send_keys()
を使ってパスワードを入力します。
ユーザー名とパスワードの入力が完了したら、次は、ユーザー名とパスワードを送信するために送信ボタンを押下します。
送信ボタンの押下は、web-driver.Session:css_select()
を使って、送信ボタンを取得します。ボタンの押下は、web-driver.ElementSet:click()
を使います。
ここまでで、ユーザー名とパスワードを入力し、それらを送信しました。 入力したユーザー名とパスワードに間違いがなければ、ログイン成功し、ログイン後のページヘ遷移します。
リンク先のページへ遷移
次は、ログイン後のページ内のリンクをクリックし、別のページへ遷移します。
ページ内のリンクを取得するには、web-driver.Session:link_search()
を使います。このメソッドの引数にa要素のname属性の値を指定します。
上記の例では、リンクテキストが「1」のリンクを取得しています。取得したリンクをクリックするには、web-driver.ElementSet:click()
を使います。
これで、リンク先のページへ遷移します。
ページ内のテキストを取得
リンク先のページへ遷移後は、ページ内要素を取得し、その要素のテキストを取得します。
要素の取得は、今までと同様、web-driver.ElementSet:css_select()
で取得します。
取得した要素のテキストを取得するには、web-driver.ElementSet:text()
を使用します。web-driver.ElementSet:text()
は要素のテキストを文字列として返します。
上記の例では、遷移後のページのp要素のテキストを取得し、print
を使ってテキストを標準出力に出力しています。
このようにして、LuaWebDriverでは、Webブラウザーを操作し、必要なページや要素へアクセスしその値を取得することができます。 今回の例では、要素の取得にCSSセレクターを使いましたが、XPathなどその他の方法で検索、取得することもできます。 CSSセレクター以外の取得方法については、web-driver.Searchableモジュールのリファレンスに記載しています。
終わりに
LuaWebDriverの基本的な使い方と主な機能を紹介しました。ここで紹介した機能以外にも便利な機能があります。 LuaWebDriverのその他の機能については、以下のドキュメントを参照して下さい。
このライブラリーは、XMLua、LuaCSと同様株式会社セナネットワークス様からの依頼を受けて開発した受託開発の成果物です。
成果物をフリーソフトウェアとして公開すると、様々なユーザーがライブラリーを使うことによって、いままで気が付かなかったバグを発見できたり、ユーザーからの要望によって、当初想定していなかった、便利な新機能を実装するきっかけとなったり、様々なメリットがあます。
このように成果物の公開によって、ライブラリーの品質も高まるので、お客さんにとっても成果物を公開するメリットがあります。
ご依頼主の株式会社セナネットワークス様には、上記のようなメリットにご理解をいただき、成果を公開できました。ありがとうございます!