selenium webdriverによるHTML要素の取得方法
今回は、node.jsからselenium webdriverを介してWEBサイトのHTMLを取得する際の話題です。
まず、selenium webdriverモジュールを読み込み、driverオブジェクトを生成してURLをGETします。
(selenium-webdriverはnpmなどで事前にインストールしておきます。)
node.js
var wb = require("selenium-webdriver"); //今回、phantomjsのghostdriverをつかったヘッドレスな環境で実行していて、ghostdriverがポート8910で起動してる。 var driver = new wb.Builder() .usingServer("http://localhost:8910") .withCapabilities(wb.Capabilities.chrome()) //実際にブラウザはないが、仮想のgoogle chromeを使用している。 .build();
driver.get(URL)でページをfetchすることで、driverオブジェクトにページ情報が格納される。
//ためしにyahooのTOPをgetしてみる driver.get("http://www.yahoo.co.jp/");
さて、ここからページのHTML要素にアクセス方法は、ID指定やXPathなどいくつかありますが、
個人的に一番使いやすいのがCSSセレクタで取得する方法です。
//wb.By.css(CSSセレクタ)で要素にアクセス driver.findElement(wb.By.css("#srchbd ul.tab > li:nth-of-type(1)")).then(function(elem){ //要素の内包テキストを取得 elem.getAttribute("innerText").then(function(txt){ console.log(txt); }); });
※node.jsではfindElementやgetAttributeは非同期で走るので、
then等でコールバックを指定する必要があります。
僕の場合もともとフロントエンドの開発が好きで
jqueryやスタイルシートでCSSセレクタに触れる機会が多かったのでかなり取っ付きやすかったです。。
要素の検索速度等を考えるとID指定の方が早いかもですね!
node.jsでコマンドライン引数を受け取る
node.jsで書いたプログラムにコマンドライン引数を渡す必要が
あったため、スニペットします。。
node.js側でprocessオブジェクトのargvプロパティによりコマンドライン引数を取得することができます。
processは標準モジュールにより設定されているグローバルオブジェクトなので、別途モジュールのインストール・requireは必要なし。
processオブジェクトの詳細はこちら
test.js
console.log(process.argv);
こんな感じでコマンドライン引数を渡すと
$node test.js arg1 arg2
配列で取得できます。
第1要素は"node"という文字列が、第2要素にはnode.jsプログラムのファイルパスが格納され、
第3要素以降には指定したコマンドライン引数が格納されています。
[ 'node', '/var/www/html/node/test.js', 'arg1', 'arg2' ]
上記以外でもargvというモジュールがあり、少しだけ取得しやすくなっているようです。
$npm install argv
test.js
var argv = require("argv"); console.log(argv.run());
結果はオブジェクトで取得できます。
{ targets: [ 'arg1', 'arg2' ], options: {} }
argvモジュールを使うと、オプションを定義・指定できたりしますが、
今回は特に使わなかったのでカットで!
argvモジュールの詳細はこちら
これ知らなかったなあ(´・ω・`)
数年前にjavasriptを初めて触ったとき、変数の中身をみるのは常にalert()だった。
それからconsole.log()を覚え現在に至る。。
ブラウザでデバッグできたりもするけど、
今でもやっぱりconsole.log()で確認するのがしっくりきます。
consoleに出力する方法がいろいろあることを最近知ったのでカキコ(´・ω・`)
1.いままで使ってたやつ
console.log()
2.実行回数をcount up
for (var i = 0; i < 5; i++) { console.count("label"); }
4.時間をはかる
これはさすがに知ってた。。
console.time("hoge"); console.timeEnd("hoge");
5.オブジェクトを表でみれる
リッチな感じですが、「添字」って何か違和感あるなあww
console.table(test);
7.グループ化
(firefox標準のコンソール(Gecko)では未サポートのようでうまく動かなかったのでchromeでcap)
console.groupCollapsed("part1"); console.log("a"); console.log("b"); console.log("c"); console.groupEnd(); console.groupCollapsed("part2"); console.log("d"); console.log("e"); console.groupEnd();
8.使いどころがいまいちわからんけど、分かりやすくできるみたい
console.error(test); console.info(test); console.warn(test);
consoleオブジェクトには他にもメソッドがあるみたいですが、
今回は割と使えそうなものをチョイスしました!
selenium - node.js - phantomJSでヘッドレスWEBサイトチェック
WEBサイトのコンテンツを自動でチェックする必要があり、
seleniumを使って自動化できないか試したのでメモ。
ちなみに、今回はヘッドレスなlinuxサーバ環境(ブラウザを立ち上げない環境)でチェックツールを実行しました。
環境
・node.js(チェックロジック)
・phantomJS(ヘッドレス環境を体現)
・selenium webdriver(チェックロジック)
phantomJSは従来のようなのブラウザによるGUI描画を必要とせず高速に処理することができ、
GhostDriverはPhantomJSを使用したWebDriver Wire Protocolを再現します。
※環境構築部分は割愛。。。
1.phantomJSのGhostDriverを起動
$ phantomjs -w
2.node.jsでselenium webdriverモジュールを読み込む
var wb = require("selenium-webdriver");
2.node.jsでwebdriverを起動、WEBサイトを読み込みチェックロジックを書く
var drivers = new wb.Builder() .usingServer("http://localhost:8910") .withCapabilities(wb.Capabilities.chrome()) .build(); drivers.get("サイトURL"); driver.findElement(wb.By.css("CSSセレクタ")).then(function(elem) { //取得したエレメントに対して何らかの処理を行う });
こんな感じでヘッドレス環境でWEBサイトのエレメントを取得して
ごにょごにょできるというわけですね。
ちなみに、ヘッドレス環境ではスクリーンショットも撮れます!
var fs = require("fs"); driver.takeScreenshot() .then(function(img) { fs.writeFile(ファイル名, img, "base64", function(error) { if(error) { throw error; } } ); });
【jquery】propとattr
既出でいまさら感満載ですが、試してみたのでカキコ。。
(jquery-version:1.11.3)
attrとpropは両者とも属性を扱うjqueryのメソッドで、
いろいろなサイトでこんな風に紹介されていますね。
prop
javascriptのプロパティ値を取得
attr
HTMLの属性値を取得
例えば、checkboxのチェック有無を取得するとこのようになる。
prop
- チェックあり
true
- チェックなし
false
attr
- チェックあり
"checked"
- チェックなし
undefined
propはcheckしたかどうかをjavascriptのプロパティ値に沿った真偽値で返すのに対し、
attrはcheckedとうい属性の値を取得しており、チェックなしの時はcheckedという属性
自体が無いのでundefinedとなるようです。
次のようなカスタム属性(arg)を扱うケースでは、attrでは取得できるものの
javascriptのプロパティ値として用意されていないのでpropでは取得できずにundefinedとなります。
<div id="test" arg="argument"></div>
ちなみに、propでもむりくりやれば取得できます。
console.log($("#test").prop("attributes")["arg"].nodeValue); ...result:"argument"
結局、propはcheckboxやselectbox、radiobuttonなどの設定値を
取得したい時に使い、それ以外の属性操作はattrでいいんじゃないでしょうか。。。
おまけ
カスタム属性を扱う場合dataメソッドを使うのがスマートかと思います。
<div id="test" data-arg="argument"></div> console.log($("#test").data("arg")); ...result:"argument"
【node.js】node inspectorでnode.jsをデバッグしてみた
今までconsoleデバッグで頑張ってきましたが、
業務でnodeを使うことが増え思い切ってデバックしてみることに...
環境設定もろもろ、エディタを乗り換えるみたいな面倒くささがあると勝手に
思っていたんですが、思いの外簡単ですんなり行けたのでメモ。。
使うのはnode-inspectorというモジュールで、Chromeを介してデバックを行います。
node inspectorのインストール
$ npm install -g node-inspector
debugのやり方
debugというオプションをつけてデバッグ対象のnodeアプリを起動します。
$ node --debug test.js
アプリを起動すると、debug portが表示される。
debugger listening on port 5859
別窓でnode-inspectorを起動する。(この例だとweb port=8081、debug portが先ほどの5859)
$ node-inspector --web-port 8081 --debug-port 5859
以下のようなメッセージが表示される。
Visit http://127.0.0.1:8889/?ws=127.0.0.1:8889&port=5859 to start debugging.
ここで、chromeにhttp://127.0.0.1:8889/debug?port=5859にアクセスすると、
debug consoleが起動します。
このへんのコマンドはbashのaliasやfunctionに書いてショートカットすると捗るかも。
.bashrc
alias nodeinspector='node-inspector --web-port 8889 --debug-port 5859' function nodedebug(){ command node --debug-brk=5859 $1; }
ちな、今回はphantom.jsのゴーストブラウザを使ったヘッドレス環境において
selenium-node.jsでのWEBサイトテスト行うといった業務内容だったんですが、
node inspectorは問題なく動いてましたね。
selenium webdriverで要素存在チェック
selenium webdriverを使ってWEBサイトの要素を取得するには、
次のようなfindElenemt(s)メソッドを使い、コールバックにより取得します。
driver.findElement(wb.By.css(セレクタ)).then(function(elem) { //〜処理 });
ただし、WEBサイトに存在しない要素を取得しようとした場合、
NoSuchElementExceptionが発生します。
try-catchで拾おうとしましたが、うまく拾えませんでした。
(理由がわからん。。。)
とりあえずisElementPresentをかませることで要素の存在チェックができるようですが、
使い方あってるのかなあ(笑)!?
driver.isElementPresent(wb.By.css(h2.p.node)).then(function (isExist) { if (isExist) { driver.findElement(wb.By.css(セレクタ)).then(function(elem) { //〜処理 }); } });