概要
Capybaraで全てのリンク先のページに対して処理をしようとして、ハマったので作りました。
リンク先のページに対して処理する4つのサンプルコードを置いておきます。
実装
全てのaタグに対して処理をします。
処理対象のHTMLサンプル
<a href="./1.html">1</a>
<a href="./2.html">2</a>
<a href="./3.html">3</a>
ページを遷移して処理するタイプ
全てのリンク先へページ遷移して処理します。
画面遷移するタイプ
for i in 0..(all('a').length-1)
all('a')[i].click
# 遷移後のページでの処理
go_back
end
新しいウインドウを開いて処理するタイプ
全てのリンク先を新しいウインドウで開いて処理します。
新しいウインドウを開くタイプ
all('a').each do |link|
url = link[:href]
parent_window = current_window
switch_to_window(open_new_window)
visit(url)
# 遷移後のページでの処理
current_window.close
switch_to_window(parent_window)
end
リンク先のページでの処理をブロックで渡す関数
全てのリンク先のHTMLを標準出力します。
ecec_all_link
def exec_all_link
for i in 0..(all('a').length-1)
all('a')[i].click
yield
go_back
end
end
ecec_all_link { puts title }
#=> Page1 Title
# Page2 Title
# Page3 Title
リンク先のページでの処理をブロックで渡して返り値をとる関数
collect_all_link
def collect_all_link
result = []
for i in 0..(all('a').length-1)
all('a')[i].click
result.push yield
go_back
end
result
end
p collect_all_link { title } #=> ["Page1 Title", "Page2 Title", "Page3 Title"]
失敗例
ハマったパターン1
別のリンクを踏むと戻っても元居たページの情報が取れない
all('a').each do |link|
link.click
go_back
end
ハマったパターン2
ページが移動しているのでループ内でも要素が取れない
all('a').each do |link|
parent_window = current_window
switch_to_window(open_new_window)
# この位置でlink[:href]が取得できない
visit(link[:href])
current_window.close
switch_to_window(parent_window)
end
まとめ
Capybaraなどブラウザを使うと、スコープがコード上正しくてもブラウザの挙動に依存するのがわかっていい勉強になりました。
Seleniumを使って動作確認していて、他のパターンは試してないです。
ご指摘などありましたら、よろしくお願いします。
ライセンス
こちらのコードはMITライセンスです。