Help us understand the problem. What is going on with this article?

MechanizeとNokogiriでリンク先のページをそれぞれスクレイピングするときのメモ(不規則なページを取得するとき)

More than 3 years have passed since last update.

問題点

前回はページの取得が、URLが規則性を持っていたので簡単でした。
今回は、取得したいURLが不規則な人名だったため、一覧ページにあるリンクから辿っていく方法でスクレイピングすることにしました。
その際、非常に苦労したし、ドキュメントもいいのが見つからなかったのでメモ。

その際に生じた問題点としては、以下のような感じです。

  • リンククリックがうまく行かなかった。
  • searchメソッドとlink_withメソッドの振る舞いの違い
  • テキスト、URL、class(id)がついていないhtmlから取得する方法

解決方法

元のファイル.html
<table class="hoges">
<tr>
  <th class="hoge">名前</th>
  <th class="hoge2"></th>
</tr>
<tr>
  <td class="hoge"><a href="namae_ichi.html">名前1</a></td>
  <td class="hoge2">Namae Ichi</td>
</tr>
scrape.rake
page = agent.get("http://www.example.com")

href_str = page.search('//td[@class="hoge"]/a/@href')[0].text
page = page.link_with(:href => href_str).click

p page.search('div.prof_1').search('table.prof td')[0].text

↑ こんな感じ!

(前後に繰り返しがついたり、そもそもmechanizeの最初に書くやつとかは省略してます。)

困った点

searchでは.clickメソッドが使えないんですね。
あとなんかat_cssメソッドも使えなかった。(これはあれか、次のclassがどのDOMタグについているかっていうことかもしれない)
あと、link_with(:dom_class => hoge ).click は、aタグにclassがついてないとダメ。今回はtabel と tdにのみclassがついてたので、そこにハマった。
あと、個人的に嬉しかったのは、searchメソッドの重ねがけができるっていう点。

↑ 結局この辺はXMLの知識があれば余裕で理解できていたのかもしれない。まだまだ力不足。

あれ、searchの重ねがけができるってことは、
href_str = page.search('//td[@class="hoge"]/a/@href')[0].text
page = page.link_with(:href => href_str).click

これももしやXPATHじゃなくてCSSで指定できたってことかな・・・。

(追記)
やってみました。
結論ダメ。
理由は、前提としてsearchで取ってきたデータ(xml?)はclickメソッド使えない。
link.clickするには、平文のhtmlじゃないとダメなんだけど、searchしてきたデータを平文にする方法がない(わからない)。
また、hrefの値を取ってくることも、CSS指定じゃ僕の力ではできなかった。
正規表現もちゃんと勉強しないとなー。苦手意識をなくさないとー。

とりま、今日はここが限界ですた。

参考にしたページ

今回の件に至るまでにいろいろ試行錯誤した中で、以下のサイトを参考に/ヒントをもらって解決した。

class Mechanize::Page::Link
http://mechanize.rubyforge.org/Mechanize/Page/Link.html
Nokogiriを使用したクローラーめも
http://qiita.com/Kenya/items/d1a2325a552d11814111
[Mechanize]リンクをクリックする方法いろいろ
http://d.hatena.ne.jp/tomoyamkung/20121020/1350721275

勝手に誤読して勝手にハマったのは次のページ

楽々スクレイピング! Ruby Mechanizeの使い方
http://www.xmisao.com/2013/10/05/ruby-www-mechanize.html

「リンクはMechanize::Page::Linkオブジェクトで、そのclick()を呼びだせばリンク先のページを取得することができる。」って書いてあるので、勝手にclickメソッドを使えばその次の行からクリック後のページになると思い込んでたw
違うよね。普通にその結果を変数に入れないと次では使えないよね、っていう。

(追記)
あ、そうか、その後にスクレイピングするからうまくいかないのかなって思った。
http://takuya-1st.hatenablog.jp/entry/20100708/1278617397
↑この記事とか、特に変数に代入しないでフォームの送信とかしてるし。
agent変数は、ちゃんとそっちに行っているのかな?? って。
でもp agent.page.search('div.prof_1').search('table.prof td')[0].textってやっても狙ったテキストが表示されなかったのよね。

(再追記)
できたし。
普通にagentを頭につけたらできた。
なんでやろ・・・トホホ。どこかで抜けてたのかな。

雑感など

最近何をするにも一番痛感しているのは、自分のプログラミング基礎力。
文系だし、独学だし、業務でも使ってないからしょうがないけど。
お作法的なこととか、ハマりやすいポイントとか、そういうところでハマることが多い。
まぁ、「基本的なチュートリアル終わったらとにかく作れ」っていう人はそういうところが大事だとわかってるからこその発言なんだろうけど。
ともあれ、そういうところが身になっていけば、いろいろ作れるようになるかも!!楽しみ。

初心者なもので、間違ってたりしたら、どんどんご指摘ください!
アドバイスもお待ちしてます。

teruringo
よろしゃーす!
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away