Posted at

Capybaraで全てのリンク先のページに対して処理する

More than 3 years have passed since last update.


概要

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ライセンスです。