概要
仕事上でNimを使ってSeleniumを書く必要があったため、その時の知見を共有します。
HaloniumというSelenium互換ライブラリを作ってくださっている方がいたのですが
Testディレクトリにサンプルがない操作が多かったため参考になると嬉しいです。
WebDriverの設定
まず他のSeleniumと同様にChromeを使って自動操作をするため、
Chromeのバージョンに合ったWebDriverをダウンロードして
環境変数に設定する必要があります。
お使いのChromeバージョン確認
chrome://settings/help
WebDriverのダウンロード場所
https://chromedriver.chromium.org/downloads
ダウンロードしてきたらwebdriverのファイルパスを環境変数へ設定してください(割愛)
各種操作
ライブラリのimport
import halonium
ブラウザの起動と遷移
# ひとつのセッションとしてChromeを起動
var session = createSession(Chrome)
# 起動するとデフォルトは小さくウィンドウモードで起動するため全画面表示
for w in session.windows:
w.maximize()
# QiitaのURLに遷移
session.navigate("https://qiita.com/")
session.navigateをすると通常通りネットワーク接続の上、
ページ遷移するため次までの処理を待つためsleepを入れることをおすすめします。
こちらは要素のクリックによって読み込みが発生するような場合にも必要です。
waitForElementで取得できるまで待機する方法もあるかと思います。
# 3秒スリープ
sleep(3000)
オブジェクトの取得(例:ログイン処理)
要素の取得は通常のSeleniumのように書くことができます。
# ログイン処理
let userName = "input[name=\"userName\"]"
let element = session.waitForElement(userName).get() # 要素が取れるまで待機
element.sendKeys("user", Key.Tab) # ユーザー名入力後にTabを入力してフォームを移動
let password = "input[name=\"password\"]"
let element2 = session.waitForElement(password).get() # 要素が取れるまで待機
element2.sendKeys("password", Key.Enter) # パスワード入力後にEnterを押す
要素取得(ClassNameSelector)
上記の取得の他、例として複数の要素をclass名で取得する場合が以下になります。
let elements = session.findElements("class-name", LocationStrategy.ClassNameSelector)
# 複数要素の単体をクリックする場合の例
elements[i].click()
LocationStrategyには以下の種別があるので、
idやnameで取得したい場合はそちらを選択することも可能です。
LocationStrategy* = enum
IDSelector = "id"
XPathSelector = "xpath"
LinkTextSelector = "link text"
PartialLinkTextSelector = "partial link text"
NameSelector = "name"
TagNameSelector = "tag name"
ClassNameSelector = "class name"
CssSelector = "css selector"
オブジェクトのクリック
こちらは関数自体シンプルなので要素の取得と合わせてサンプルを置いておきます。
let button1 = session.waitForElement("#button_1").get()
button1.click()
おまけ:ローカルにダウンロードしたファイルの操作
こちらはselenium処理とは異なりますが、
自動操作した場合ファイルをダウンロードしてきて〜なんて話が多いのでこちらも例を。
# こちらはnimの標準ライブラリなので基本追加でもOK
import options, os, times, strutils, sequtils
# 移動先のフォルダが無ければ作成する
let path = "保存フォルダのパス"
# フォルダがなければ作成
if not existsDir(path):
os.createDir(path)
let dl_path = os.getHomeDir() & "Downloads"
# ホームディレクトリのDownloadsからcsvを検索
for f in walkFiles(dl_path & "/*.csv"):
# 更新日時が1時間以内のものを保存フォルダに移動させる
if getLastModificationTime(f) > (now() - minutes(60)).toTime:
# ファイル名をいじる場合には、walkFilesでは
# fにフルパスが渡ってくるためextractFilenameでファイル名だけにします。
# let now_dir = dl_path & "/" & extractFilename(f)
os.moveFile(f, path & "/" & extractFilename(f))