Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

初めてのWebスクレイパー構築ガイド 第2回:Mechanizeでリンク・フォーム操作を自動化する

このチュートリアルでは、Mechanizeを使ってリンクのクリック、フォームへの入力、ファイルのアップロードを行う方法を学びます。さらに、Mechanizeのページオブジェクトを自在に扱う方法や、Google検索を自動化してその結果を保存する方法についても解説します。

目次

  • 単一ページとページネーションの違い
  • Mechanizeとは
  • エージェント(Agent)
  • ページ(Page)
  • Nokogiriメソッドの活用
  • リンク操作
  • クリック操作
  • フォーム操作

単一ページとページネーション

これまでのパートでは、Nokogiriを使って単一ページからデータを抽出する方法を見てきました。これは良い基礎となりましたが、次の一歩として、複数ページからコンテンツを抽出する方法を学ぶ必要があります。

というのも、私たちが解決しようとしている問題は、140以上のエピソードからコンテンツを取得することです。これは1つのWebページに収まる量をはるかに超えています。つまり、ページネーション(ページ送り)に対応し、「ウサギの穴」のように続くコンテンツをたどっていく方法を考える必要があるのです。

ここでNokogiriの出番は終わり、Mechanizeという便利なGemが登場します。

Mechanizeとは

Mechanizeは、多くの便利な機能を備えた強力なツールです。その本質は、コンテンツを抽出したいWebサイトとのやり取りを自動化できることにあります。Capybaraを使ったテストで見たことがある機能に少し似ていると感じるかもしれません。

誤解しないでほしいのですが、Nokogiriで単一ページを扱うだけでも十分に楽しいものです。しかし、より複雑なデータ抽出タスクには、もう少しパワーが必要になります。Mechanizeを使えば、必要なだけページをクロールし、その要素とやり取りすることで、人間の行動を模倣・自動化できます。かなり強力ですよね。

このGemを使えば、リンクをたどったり、フォームフィールドに入力してデータを送信したりできるだけでなく、Cookieの扱いまで可能です。つまり、ユーザーがプライベートセッションにログインする動作を再現し、自分だけがアクセスできるサイトからコンテンツを取得することもできるのです。

認証情報でログインフォームに入力し、Mechanizeにその後の手順を指示すればよいのです。リンクのクリックもフォームの送信もできるため、このツールでできないことはほとんどありません。MechanizeはNokogiriと密接な関係があり、Nokogiriに依存しています。そして、この素晴らしいGemの作者の一人が、またしてもAaron Pattersonなのです。

Mechanizeエージェントのインスタンス化

実際にMechanizeを使い始める前に、まずMechanizeエージェントをインスタンス化する必要があります。

some_scraper.rb

このagentは、Nokogiriで行ったのと同じように、ページを取得するために使用します。

some_scraper.rb

ここでは、MechanizeエージェントがポッドキャストのページとそのCookieを取得しました。

ページコンテンツの抽出

これで抽出準備が整ったページを手に入れました。実際に抽出する前に、inspectメソッドを使って内部構造を覗いてみることをおすすめします。

some_scraper.rb

出力はかなりのボリュームになります。Mechanize::Pageオブジェクトが何で構成されているのか、自分の目で確かめてみてください。ページのすべての属性がここに表示されます。

個人的には、抽出したいデータを切り分ける際に、このオブジェクトは非常に便利だと感じています。

出力例

HTMLページそのものを見たい場合は、bodyまたはcontentメソッドを付け加えるだけです。

some_scraper.rb

このポッドキャストサイトはページ上の要素が少ないので、参考としてgithub.comから返されるMechanize::Pageも紹介しておきます。こちらはより多様なコンテンツを含んでおり、こうした構造に慣れておくことは重要だと思います。

github.comの出力例

ポッドキャストの話に戻ると、エンコーディング、HTTPレスポンスコード、URI、レスポンスヘッダーなども確認できます。

some_scraper.rb

出力例

さらに深く掘り下げたい場合には他にも多くの情報がありますが、ここではこの程度にとどめておきます。

Nokogiriメソッドの活用

  • at
  • search

Mechanizeは内部的にNokogiriを使用してページからデータをスクレイピングします。したがって、最初の記事で学んだNokogiriの知識は、Mechanizeのページオブジェクトにもそのまま適用できます。つまり、一般的にはページ間の移動にはMechanizeを、実際のスクレイピングにはNokogiriのメソッドを使うことになります。

例えば、単一のオブジェクトを検索したい場合はatを、特定のページ上でセレクターに一致するすべてのオブジェクトを取得したい場合はsearchを使います。言い換えれば、これらのメソッドはNokogiriのドキュメントオブジェクトでもMechanizeのページオブジェクトでも動作するということです。

some_scraper.rb

出力例

リンク操作

  • links
  • link_with
  • links_with

サイト全体を思い通りにナビゲートすることもできます。Mechanizeの最も重要な機能は、おそらくリンクを自由に扱える点でしょう。そうでなければ、Nokogiri単体で十分だったはずです。ページにリンクを問い合わせると何が返ってくるのか、見てみましょう。

some_scraper.rb

大量のリンクが出力されましたね。ひとつずつ分解してみましょう。Mechanizeに他の場所を見るよう指示していないため、最初のページだけからのリンク配列が返されています。Mechanizeはページを上から順に走査し、リンクのリストを返します。

ちなみに、これは私のポッドキャストサイトのリデザイン後の最終結果でもあります。デモ用としてはこのバージョンの方が分かりやすいと思います。最終的な成果物がどんな見た目になるのか、そしてなぜ古いSinatraサイトをスクレイピングする必要があったのか、その理由もなんとなく感じてもらえるでしょう。

いつものように、そこからテキストだけを抽出することもできます。

some_scraper.rb

出力例

リンクをまとめて取得できるのは非常に便利ですが、場合によっては絞り込みが必要です。幸い、必要なものを精密に選び出すためのツールがいくつか用意されています。

some_scraper.rb

特定の条件(例えばテキストなど)に一致するリンクを探したい場合は、links_withlink_withといったより使いやすいAPIが利用できます。また、同じFocusというリンクが複数ある場合は、角括弧[]を使ってページ上の特定の番号のものを指定できます。

some_scraper.rb

リンクのテキストではなくリンク自体を探したい場合は、特定のhrefを指定するだけです。Mechanizeは柔軟に対応してくれます。textの代わりにhrefを渡せばよいのです。

some_scraper.rb

目的のテキストを持つ最初のリンクだけを見つけたい場合は、次のような構文も使えます。とても便利で、少し読みやすくなります。

some_scraper.rb

では、そのFocusリンクの先に何が隠れているのか、実際にたどってみましょう。クリックしてみます!

クリック操作

some_scraper.rb

これで先ほどと同じように長いリンクのリストが取得できます。.click.linksを組み合わせるのがいかに簡単か分かりますね。Mechanizeがリンクをクリックし、新しいページへ移動してくれます。さらにリンクのリストを要求しているので、新しいページ上でMechanizeが見つけられるすべてのリンクが返されます。

例えば、同じインタビュー対象者へのテキストリンクが2つあり、1つはタグページへ、もう1つは最近のエピソードへリンクしているとしましょう。それぞれのページからリンクを取得したい場合です。

some_scraper.rb

これで両方のページのリンクリストが得られます。インタビュー対象者の各リンクを反復処理すると、Mechanizeがクリックされたリンクをたどり、新しいページで見つけたリンクを収集してくれます。以下に、組み合わせの例をいくつか紹介します。始める際の参考にしてください。

some_scraper.rb

フォーム操作

  • submit
  • field_with
  • checkbox_with
  • radiobuttons_with
  • file_uploads

次にフォームを見てみましょう!

some_scraper.rb

出力例

formsメソッドを使うと、フォームが1つしかなくても配列が返されます。フォームの名前が"f"であることが分かったので、単数形のformメソッドを使ってそのフォームに絞り込むことができます。

some_scraper.rb

form('f')を使うことで、作業対象となる特定のフォームを選び出せました。その結果、配列ではなく単一のフォームオブジェクトが返されます。

テキスト入力フィールドの名前(q)も識別できます。

この名前を指定して、Rubyの属性のように値を設定できます。必要なのは新しい値を代入することだけです。上記の出力例から、デフォルトでは空であることが分かるでしょう。

some_scraper.rb

出力例

ご覧のとおり、テキストフィールドの値がNew Google Searchに変わりました。あとはフォームをsubmitして、Googleが返すページから結果を収集するだけです。これほど簡単なことはありません。今度は別のキーワードで検索してみましょう!

some_scraper.rb

ここではCSSセレクターh3.rで検索結果の見出しを特定し、そのtextをマッピングして、結果を整形して出力しました。難しくなかったですよね?簡単な例ではありますが、これを使えば無限の可能性が広がると考えてください。

出力例

Mechanizeにはさまざまな入力フィールドが用意されており、ファイルのアップロードさえも可能です。

  • field_with
  • checkbox_with
  • radiobuttons_with
  • file_uploads

ラジオボタンやチェックボックスも名前で識別し、予想どおりcheckメソッドでチェックできます。

some_scraper.rb

optionタグは、ドロップダウンリストから項目を1つ選択するために使われます。これも同様に名前で対象を特定し、選択したいオプションの番号を指定します。

some_scraper.rb

ファイルアップロードは、フォームにテキストを入力するのと似た方法で、Rubyの属性のように設定します。アップロードフィールドを特定し、転送したいファイルのパス(ファイル名)を指定するだけです。言葉にすると複雑に聞こえますが、実際は簡単です。見てみましょう。

some_scraper.rb

まとめ

どうでしょうか、魔法など何もないことが分かりましたね!これであなたも自分で楽しく試せる準備が整いました。NokogiriとMechanizeについてはまだ学ぶべきことがいくらかありますが、不必要な部分に時間をかけすぎるよりも、実際に触って遊んでみて、初心者向け記事の範囲を超える問題に直面したときにドキュメントを調べるのがおすすめです。

このGemがいかにシンプルで美しく、どれほどのパワーを提供してくれるか感じてもらえたなら嬉しいです。ご存じのとおり、大きな力には責任が伴います。法的な枠組みの中で、APIが利用できない場合に使うようにしましょう。日常的に使う機会は多くないかもしれませんが、本格的なスクレイピングが必要になったとき、これらのツールは本当に役立つはずです。

  1. 「Webページがブラウザの速度を低下させています」エラーの解決方法【Firefox】

    Firefoxで「Webページがブラウザの速度を低下させています。停止しますか?それとも待機しますか?」というメッセージに悩まされていませんか?これは、ブラウジング中に遭遇する最も一般的なFirefoxのエラーメッセージの一つです。多くのユーザーから、ウェブページを開こうとした際にこの通知が突然表示されるという報告が寄せられています。「停止する」を選択するとエラーメッセージは一旦消えますが、15〜30秒後には再び表示されるという不思議な現象も起こります。 こうした問題に直面すると、デバイスがウイルスやマルウェアに感染していないかと疑うのが自然ですが、今回はそのケースではありません。Mozil

  2. ブラウザはどの程度プライベートであるべき?知っておきたいセキュリティとプライバシーの重要性

    ブログ概要 – ウェブブラウザを選ぶ際、そのセキュリティやプライバシー機能に注目していますか?実はウェブブラウザも私たちのデータを収集・利用することがあります。この記事では、ブラウザがどの程度プライベートであるべきかを詳しく解説します。 ブラウザはインターネットを閲覧するために欠かせないツールです。多くの人は「怪しいウェブページを見なければ安全だ」と考えています。しかし、ブラウザからの情報漏洩や、収集されたデータがターゲット広告に利用されるというニュースは珍しくありません。では、ウェブブラウザは本当に私たちにとって安全なのでしょうか?本記事で詳しく見ていきましょう。 インターネットの普及当