はじめに
Seleniumとは、WebアプリケーションのUIテストツール。
動的なサイトのスクレイピングツールとしても使われている。
今回はSeleniumをNode.jsで動かす方法を紹介する。
ドキュメント(英語版)
使用方法
事前準備(Windowsの場合)
インストール
npm i selenium-webdriver
ChromeDriverのダウンロード
ChromeDriver – WebDriver for Chrome
https://sites.google.com/a/chromium.org/chromedriver/downloads
実行ファイルと同じパスに配置
基本操作
ライブラリのインポート
const webdriver = require('selenium-webdriver');
const { Builder, By, until } = webdriver;
良く使うBuilder, By, untilをここで定義
設定(Chromeの場合)
const capabilities = webdriver.Capabilities.chrome();
capabilities.set('chromeOptions', {
args: [
'--headless',
'--no-sandbox',
'--disable-gpu',
`--window-size=1980,1200`
// other chrome options
]
});
Chrome Options
ブラウザの立ち上げ
const driver = await new Builder().withCapabilities(capabilities).build();
// ブラウザを終了する
driver.quit();
※基本的に返り値がpromiseなので、async/awaitを使う
ページ移動
await driver.get('https://www.youtube.com/');
要素の特定
// タグ名で特定
let el1 = await driver.findElement(By.tagName('hoge'));
let el2 = await driver.findElement({ tagName: 'hoge' });
// idで特定
let el1 = await driver.findElement(By.id('foo'));
let el2 = await driver.findElement({ id: 'foo' });
// classで特定
let el1 = await driver.findElement(By.className('bar'));
let el2 = await driver.findElement({ className: 'bar' });
// cssセレクタで特定
let el1 = await driver.findElement(By.css('#foo'));
let el2 = await driver.findElement({ css: '#foo' });
// 複数要素の特定
let els1 = await driver.findElements(By.css('.bar'));
let els2 = await driver.findElements({ css: '.bar' });
要素から属性の取得
let el = await driver.findElement(By.css('#foo'));
// テキストを取得
let text = await el.getText();
// ↑だとなぜか動かない場合はこちら
let innerHTML = await el.getAttribute('innerHTML');
// その他属性の取得
let href = await el.getAttribute('href');
応用編
待ち処理
/**
* xxx:関数名
* timeout:タイムアウト時間(ミリ秒)
*/
await driver.wait(until.xxx(), timeout);
要素の出現
// 要素の出現を待つ
await driver.wait(until.elementLocated(By.id('foo')), 10000);
await driver.wait(until.elementsLocated(By.className('bar')), 10000);
URL条件
// 完全一致
await driver.wait(until.urlIs('xxx'), 10000);
// 部分一致
await driver.wait(until.urlContains('xxx'), 10000);
// 正規表現
await driver.wait(until.urlMatches(/xxx/), 10000);
タイトル条件
// 完全一致
await driver.wait(until.titleIs('xxx'), 10000);
// 部分一致
await driver.wait(until.titleContains('xxx'), 10000);
// 正規表現
await driver.wait(until.titleMatches(/xxx/), 10000);
特定要素のテキスト条件
let el = await driver.findElement(By.css('#foo'));
// 完全一致
await driver.wait(until.elementTextIs(el, 'xxx'), 10000);
// 部分一致
await driver.wait(until.elementTextContains(el, 'xxx'), 10000);
// 正規表現
await driver.wait(until.elementTextMatches(el, /xxx/), 10000);
要素の状態
let el = await driver.findElement(By.css('#foo'));
// enabled
await driver.wait(until.elementIsEnabled(el), 10000);
// disabled
await driver.wait(until.elementIsDisabled(el), 10000);
// selected
await driver.wait(until.elementIsSelected(el), 10000);
// not selected
await driver.wait(until.elementIsNotSelected(el), 10000);
// visible
await driver.wait(until.elementIsVisible(el), 10000);
// not visible
await driver.wait(until.elementIsNotVisible(el), 10000);
スクリーンショットを撮る
// スクリーンショット画像をbase64でエンコードしたもの
let base64 = await driver.takeScreenshot();
// bufferに変換
let buffer = Buffer.from(base64, 'base64');
サンプル
Youtubeのスクリーンショットを撮るサンプル
sample.js
const fs = require('fs');
const { promisify } = require('util');
const webdriver = require('selenium-webdriver');
const { Builder, By, until } = webdriver;
const capabilities = webdriver.Capabilities.chrome();
capabilities.set('chromeOptions', {
args: [
'--headless',
'--no-sandbox',
'--disable-gpu',
`--window-size=1980,1200`
]
});
// awaitを使うので、asyncで囲む
(async () => {
// ブラウザ立ち上げ
const driver = await new Builder().withCapabilities(capabilities).build();
// Youtubeへ移動
await driver.get('https://www.youtube.com/');
// 検索ボックスが表示されるまで待つ
await driver.wait(until.elementLocated(By.id('search')), 10000);
let base64 = await driver.takeScreenshot();
let buffer = Buffer.from(base64, 'base64');
// bufferを保存
await promisify(fs.writeFile)('screenshot.jpg', buffer);
// ブラウザ終了
driver.quit();
})();