テストしないSelenium :: KNIMEでWebスクレイピングしてみよう

こんにちは！ みなさんSeleniumで自動テストでクロスブラウザーでGridですか！！
私 最近ちょっとアレなんですよ〜


Seleniumは「ブラウザーをプログラムから操作する」ライブラリーです。
==============================================================

Seleniumについてのよくある誤解に「Seleniumは自動テストライブラリーである」というのがあります。

誤解なんですよ！ Seleniumは **「ブラウザーをプログラムから操作する」** だけのライブラリーです。自動テストとの親和性が高いのは間違いありませんが、もっと別のことで使ってしまっても何も問題ありません。

自動テスト以外での利用についての記事をWeb上であまり見かけませんが、自動テストの次に多い用途はWebスクレイピングではないでしょうか。


WebスクレイピングでのSeleniumの活用
=====================================

Webスクレイピングとは、Webサイト上で公開されている何らかのデータをどうにかして取得する処理のことです。この発想自体はあまり特別なものではなく、昔から様々なツールにより実現されています。

Webスクレイピングで重要なのは、どうやればお目当てのデータだけを抽出できるか、ということだと思います。
大半の場合、お目当てのデータのありかは特定のURLから取得可能なHTMLに埋め込まれていますから、Webブラウザーよりも単にHTTPクライアントと呼んだ方が適切そうな軽量なツールで間に合います。

ところが、お目当てのデータを出現させるために複雑な手順や前提が必要になる場合は、軽量なツールではなかなか実現できません。
昔はブラウザー風の何かを併用して苦心しながら実現したりしましたが、今はSeleniumでブラウザーそのものを利用した方が手っ取り早く確実に動くものを作れるようになったと思います。
私は実際、仕事の一環でWebスクレイピング処理をSeleniumで実装していたりします（優秀なアナリストにとって重要な諸々の統計データが、洗練された形で公開されているとは限りませんので、そこの苦労を肩代わりするためのツールとして利用しています）。

なお、スクレイピングして得られたデータを処理ごとに使い捨てにすることはなかなか無く、一般的なデータ処理「ETL(Extract, Transform, Load)」と組み合わせてファイルやデータベースに永続的に記録することが多いです。このような処理はスクラッチで書いたりもしますが、誰が書いても車輪の再発明になりそうな処理ですので汎用的なETLソフトで実現しても良いかと思います。

今回は、仕事ではまだ使っていない構成なんですが、ETLにも使えるソフト「KNIME（ナイム）」から直接Seleniumをいじれることがわかったので、これをかんたんに試用しつつ、テストでの利用とは少し違ったSeleniumの利用形態をご紹介しようと思います。


KNIMEでSeleniumを使ってみよう
=================================

KNIMEはスイス製の商用ソフトウェアで、統計分析のためのプラットフォームです。一般的にはETLソフトの枠内では語られないソフトですが（Qiitaでは[機械学習のソフト](http://qiita.com/junkonakajima/items/aeb5e16216a86d18ffb4)などとしての記述が目立ちますね）、分析前後のデータ加工機能でやれることはETLソフトそのものです。表形式のデータを処理するノードを設定し、GUI上でノード間のフローを作図すると、コーディング無しに一連のデータ処理フローを実装することができます。

![サンプル](https://qiita-image-store.s3.amazonaws.com/0/33963/b6191afc-546f-6e39-d1c8-e7bb1b6bc711.png)

PC上で動くGUIツールの「Analytics Platform」は無料で利用することが可能です。他の無料のETLソフトに比べて私が好きなところは、

* GUIが比較的こなれていて、Excelしか扱ったことがない人でもギリギリ扱えるレベル。
* ワークフロー図がSVGとして別途管理されるため、実装との乖離が非常に少ない有用な開発ドキュメントとして再利用できる。
* 定義ファイルがXMLファイルなのでGitなどの一般的なSCMで差分管理できる

といったあたりです。

## KNIME Analytics Platformのインストール

では、まずKNIME Analytics Platformからインストールしてみましょう。
KNIMEの公式サイト https://www.knime.org/ にアクセスして、メニューの「PRODUCTS」から「KNIME Analytics Platform」を選択してください。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/233eb34f-f4b8-9433-d38a-3ea0fd48c4a1.png)

KNIME Analytics Platformの紹介ページに移動します。
左のメニューの「Downloads」か、紹介ページ中のボタン「Download Now」をクリックしましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/09291a13-9d35-8cdd-f01b-1ba1cd9d9b82.png)

ダウンロードページに移動します。一見 ユーザー登録が必要に見えますが、ページ真ん中の「Download KNIME」を押せば登録無しにダウンロードできます。（ニュースレターを受け取りたい人はぜひ登録しましょう！）

![](https://qiita-image-store.s3.amazonaws.com/0/33963/bd68c842-2c8e-9e60-341f-83bc48741ead.png)

Windows・Mac・Linux用のダウンロードリンクがそれぞれありますので、使いたいもののリンクをクリックしましょう。フォームが展開され、ダウンロードできるようになります。この記事では例としてMac用のものを選択し、ダウンロードします。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/a6096e91-3e24-0909-3451-c7ef3b4eddba.png)

なお、「all free extensions」と書かれているパッケージの方がサードパーティー製ノードがいろいろ最初から入っていて嬉しい感じですが、ファイルサイズが大きくてダウンロードがしんどいので、最初のお試しのうちはextensions無しのパッケージを選ぶと良いでしょう。

ダウンロードしたファイルを展開すると、Mac版の場合は次の画像のようになります。パッケージをApplicationsフォルダーにコピーするだけで、インストールが済むようになっています。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/f0193e0e-baa5-ce23-5c84-93ea78febe65.png)

## Selenium Nodesのインストール

KNIME Analytics Platform向けの無償の追加機能には、Seleniumを直接利用することができる「Selenium Nodes」があります。これを追加でインストールしてみましょう。
http://seleniumnodes.com/

KNIME Analytics Platformの起動後、メニュー「Help」から「Install New Software...」を選択しましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/af3776ff-6949-b4e6-261d-484829d9dad6.png)

カンの良い方は気づいたかもしれませんが、KNIME Analytics PlatformのベースになっているソフトはEclipseで、追加機能のインストール方法もEclipseと同じです。[Selenium Nodesのサイトに載っている手順](http://seleniumnodes.com/download)のとおり、更新サイトを追加して「Selenium for KNIME」をインストールしましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/4db8ebfc-9ffb-ecaa-c3fb-d47e23e0f9ac.png)

インストール後、表示されるダイアログにしたがい再起動したら、KNIMEのPreferences設定メニューから、Selenium固有の設定をしましょう。Macの場合は「環境設定...」からでも設定可能です。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/3b96ee6c-17d3-8114-4c45-b02c7780c311.png)

Preferencesの「KNIME」メニューの中に、「Selenium」が追加されています。ChromeDriverサーバーの実行ファイルのパスなどはここに設定しましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/ab97084c-4a2e-6dcb-6d7e-a81727249016.png)


これで準備は完了です。


Selenium Nodesの基本ノードを使ってみよう
=========================================

## KNIMEワークフローの新規作成

では、KNIMEワークフローを新しく作成して、Selenium Nodesを試用してみましょう。
メニュー「File」から「New...」を選択してください。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/c8815035-7508-920c-841b-11af42dc3e31.png)

ウィザードが表示されます。
「New KNIME Workflow」を選択して、ボタン「Next」をクリックしましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/230d632d-7d37-64e8-8fe8-d431ba9df45b.png)

「Name of the workflow to create」に、ワークフローの名前を入力します。ここでは「Selenium_sample_project」としてみます。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/e6858775-cf0e-d221-3f04-c8219fb73199.png)

これでワークフローの新規作成は完了です。

Selenium的な処理ノードは、「Node Repository」のSeleniumグループにあって、ワークフロー上にドラッグ＆ドロップして並べていくことができます。これらのノードを利用して、基本的な処理を作ってみましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/1900aa5e-6542-39a0-67bd-0ee09059560b.png)

## リモート操作するブラウザーの定義

リモート操作するブラウザーの定義には「WebDriver Factory」を使います。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/0c18ac1f-6c86-ed6b-125e-2f5061e3f49c.png)

ノードをダブルクリックすると、設定画面が開きます。
タブ「Options」のプルダウンメニュー「WebDriver」から、リモート操作するブラウザーを選択できます。ここではChromeを選択してみましょう。
選択後にボタン「Test WebDriver」を押すと、選択したブラウザーを操作できるかテストできます。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/7442e8fd-3506-477e-710b-0467c3c45b30.png)

## 指定したURLへの遷移

指定したURLへの遷移には「Start WebDriver」を使います。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/2fd4cdfe-32be-6de8-3da5-7ea26f38fe42.png)

ここではサンプルとして、日本Seleniumユーザーコミュニティが提供する次のサイトにアクセスするように設定してみましょう。
http://example.selenium.jp/reserveApp/
ノードの設定画面で、タブ「Options」のフィールド「URL」に、サイトのURLを入力します。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/9baae9e1-a439-9f83-5b71-5953d88d6a62.png)

では、「WebDriver Factory」と接続してみましょう。緑色の四角部分同士で、ドラッグ＆ドロップで線を引いて接続することができます。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/20f7a041-b954-d60b-a2b2-c3e17cc04dbd.png)

## 要素の検出

要素の検出には「Find Elements」を使います。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/eb64898a-581d-e13e-fd11-95a50497a25e.png)

「Find Elements」は、「Start WebDriver」を前段に接続しないとノードの設定画面を開くことができません。次の画像のように黒い矢印部分で接続しましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/bf183e77-6a6b-c151-489b-f05744d689cb.png)

接続後、ノードの設定画面では、タブ「Options」のプルダウンメニュー「Find by」にロケーターの種類、フィールド「Query」にロケーター文字列を入力します。
ここではサンプルとして、年数のフィールドのIDをロケーターとして設定します。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/60022f85-1543-6ef8-d9af-bdf93c8614a6.png)


## 要素が持つ値の取得

要素が持つ値の取得には、valueなど属性値の場合には「Extract Attribute」を使い、包含する文字列の場合には「Extract InnerHTML」を使います。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/a355243a-962b-4aee-ef90-c104d94e808e.png)

ここでは、年数のフィールドのvalue属性の値を取得するために「Extract Attribute」を使います。
「Extract Attribute」も「Find Elements」と同様に、前段の接続が無いとノードの設定画面を開くことができません。まず、次の画像のように接続しましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/76190859-b988-cfd1-aa6e-14f774048112.png)

接続後、ノードの設定画面で、タブ「Options」のプルダウンメニュー「Input」に前述の「Find Elements」で得られた要素、フィールド「Attribute name」に属性の名前を入力します。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/645639a7-aed1-aa59-5fa7-31534fa0d409.png)

## リモート操作しているブラウザーを閉じる

リモート操作しているブラウザーを閉じるには「Quit WebDriver」を使います。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/222df0f7-905f-4bee-b8a9-c3467f38ed33.png)

「Quit WebDriver」を最後に接続したら、Seleniumワークフローのサンプルは完成です。
なお、ノードには任意のラベル文字列を記載することができますので、わかりやすいラベルを書いておきましょう。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/d4e360f2-4f3e-f622-d2cf-12b3fb1e3ea0.png)

## ワークフローを実行する

すべて実行するボタン ![](https://qiita-image-store.s3.amazonaws.com/0/33963/6a64350a-3b89-b7a2-7421-cf456f5d88e4.png) を押すと、一連のワークフローが実行され、要素への参照や値がすべて表形式データとして得られます。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/d846b767-17f7-2045-6623-243ca76d8137.png)

得られた表形式データは、さらに後段にノードを追加することで、ExcelやCSVなどのファイル、MySQLなどのRDBMSなどに、KNIMEから直接保存することが可能です。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/b86d9573-62a3-d1e5-283f-c1a0f4714e5a.png)


Selenium Nodesを使う場合の設計パターン
========================================

## メタノードの作成・再利用によるページオブジェクトっぽい感じ

逐次処理・表形式データの積み上げであるKNIMEの処理の中でページオブジェクトパターンをやるのは難しいかもしれません。しかしながら、要素の検出処理をひたすら積み上げたメタノードを定義すると、ページオブジェクトっぽい感じにはできるかもしれません。

例えば次のように、複数の「Find Elements」ノードを積み上げてから、

![](https://qiita-image-store.s3.amazonaws.com/0/33963/0c7cbe85-c9f4-3839-31c3-ac89dbfe861b.png)

「Encapsulate into Wrapped Metanode」を選択して、

![](https://qiita-image-store.s3.amazonaws.com/0/33963/24ec1697-1117-5510-cebf-ec16f6d83076.png)

3つの定義をまとめたメタノードを作成してみます。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/f5cd950e-d30f-a380-3609-f4bdff00410f.png)

このメタノードの後段に接続する「Extract Attribute」では、複数の候補から要素を選べるようになります。

![](https://qiita-image-store.s3.amazonaws.com/0/33963/c57f7981-33de-2407-6ab9-e57f274e8eef.png)

このようなメタノードをページごとに作り込んでおき、必要になったワークフローの最初の方に仕込んでおけば、要素の定義を集約することもできてなんとなくページオブジェクトっぽくなるのではないでしょうか。