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

最初のWebスクレイパーの構築、パート1

Rubylandには、過去数年間ウェブスクレイピングのスポットライトを占めてきた2つの宝石、NokogiriとMechanizeがあります。実際の例を使って実行する前に、これらのそれぞれについて記事を使用します。

トピック

  • ウェブスクレイピング?
  • 許可
  • 問題
  • ノコギリ
  • 抽出?
  • ページ
  • API
  • ノードナビゲーション

ウェブスクレイピング?

ウェブや画面のスクレイピングよりももっと凝った用語があります。 WebハーベスティングとWebデータ抽出により、何が起こっているのかがすぐにわかります。 Webページからのデータの抽出を自動化できますが、それほど複雑ではありません。

ある意味で、これらのツールを使用すると、人間のWebブラウジングを模倣して自動化できます。関心のある種類のデータのみを抽出するプログラムを作成します。特定のデータをターゲットにすることは、CSSセレクターを使用するのとほぼ同じくらい簡単です。

数年前、私は数百万の短いビデオがあったが、それらをまとめてダウンロードするオプションがないオンラインビデオコースを購読しました。私は自分ですべてのリンクを調べて、恐ろしい「名前を付けて保存」する必要がありました。それは一種の人間のウェブスクレイピングでした。そのようなものを自動化するための知識が不足しているときに、私たちがしばしば行う必要があることです。コース自体は大丈夫でしたが、その後はサービスを利用しなくなりました。面倒すぎました。

今日、私はそのような心を溶かすUXについてはあまり気にしません。私のためにダウンロードを行うスクレーパーは、一緒に投げるのにほんの数分しかかかりませんでした。大したことはありません!

始める前に、すぐに分解してみましょう。全体をいくつかのステップにまとめることができます。まず、必要なデータが含まれているWebページをフェッチします。次に、そのページを検索して、抽出する情報を特定します。

最後のステップは、これらのビットをターゲットにし、必要に応じてスライスし、それらを保存する方法と場所を決定することです。よく書かれたHTMLは、このプロセスを簡単で楽しいものにするための鍵となることがよくあります。より複雑な抽出の場合、構造化されていないマークアップを処理する必要があると、苦痛になる可能性があります。

APIはどうですか?とても良い質問です。 APIを使用してサービスにアクセスできる場合、多くの場合、独自のスクレーパーを作成する必要はほとんどありません。このアプローチは主に、そのような便利さを提供しないWebサイト向けです。 APIがない場合、これがWebサイトからの情報の抽出を自動化する唯一の方法であることがよくあります。

あなたは、この削り取りが実際にどのように機能するのかと疑問に思うかもしれません。ディープエンドに飛び込むことなく、簡単な答えは、ツリーデータ構造をトラバースすることです。 Nokogiriは、フィードしたドキュメントからこれらのデータ構造を構築し、関心のあるビットを抽出の対象にすることができます。たとえば、CSSは、ツリーのデータ構造を検索するためのツリートラバーサル用に記述された言語であり、データ抽出に使用できます。

さまざまなアプローチと解決策があります。 Rubylandには、ここ数年注目を集めている2つの宝石があります。多くの人々は今でもHTMLスクレイピングのニーズをNokogiriとMechanizeに依存しています。どちらもテストされ、使いやすく、高い機能を備えていることが証明されています。両方を見ていきます。ただし、その前に、この短い紹介シリーズの最後に解決する問題について少しお話ししたいと思います。

許可

スクレイピングを開始する前に、データ抽出のためにアクセスしようとしているサイトの許可を得ていることを確認してください。たとえば、サイトにAPIまたはRSSフィードがある場合、その目的のコンテンツを取得するのが簡単であるだけでなく、それが選択の合法的なオプションである可能性もあります。

あなたが彼らのサイトで大規模なスクレイピングを行うならば、誰もがそれを評価するわけではありません—当然のことながらそうです。興味のある特定のサイトについて教育を受け、問題を起こさないようにしてください。深刻なダメージを与える可能性は低いですが、無意識のうちにトラブルの危険を冒すことは道ではありません。

問題

新しいポッドキャストを作成する必要がありました。デザインは私が望んでいた場所ではなく、新しい投稿を公開する方法が嫌いでした。くそーWYSIWYGs!少しコンテキスト。約2年前、ポッドキャストの最初のバージョンを作成しました。アイデアは、シナトラで遊んで、超軽量のものを作ることでした。私はほとんどすべてをテーラーメードしたので、いくつかの予期しない問題に遭遇しました。

Railsから来て、それは間違いなく私が感謝する教育的な旅でしたが、GitHubページを介してGitHubを介して展開できた静的サイトを使用しなかったことをすぐに後悔しました。新しいエピソードを展開して維持することは、私が探していた単純さを欠いていました。しばらくの間、私はより大きな魚を揚げることに決め、代わりに新しいポッドキャスト素材の作成に集中しました。

この夏、私は真剣になり始め、GitHubページを介してホストされているMiddlemanサイトで作業しました。ショーのシーズン2では、何か新鮮なものが欲しかった。新しいシンプルなデザイン、新しいエピソードを公開するためのMarkdown、そしてHerokuとの最初の戦いはありません—天国!問題は、ミドルマンと連携するために最初にインポートして変換する必要のある139のエピソードが周りにあるということでした。

投稿には、ミドルマンは.markdownを使用します データのいわゆるフロントマターを持つファイル—基本的に私のデータベースを置き換えます。この転送を手動で行うことは、139エピソードのオプションではありません。それが計算の目的です。古いWebサイトのHTMLを解析し、関連するコンテンツをスクレイピングして、ミドルマンで新しいポッドキャストエピソードを公開するために使用するブログ投稿に転送する方法を見つける必要がありました。

したがって、次の3つの記事では、Rubylandでそのようなタスクに一般的に使用されるツールを紹介します。最後に、私のソリューションを検討して、実用的なものも紹介します。

ノコギリ

Ruby / Railsにまったく慣れていない場合でも、この小さな宝石についてすでに聞いたことがある可能性は非常に高いです。名前は頻繁に削除され、簡単に付けられます。のこぎりが日本語で「のこぎり」であることを多くの人が知っているかどうかはわかりません。

ツールの機能を理解すれば、これは適切な名前です。この宝石の作成者は、素敵なTenderlove、AaronPattersonです。 Nokogiriは、XMLおよびHTMLドキュメントをデータ構造(より正確にはツリーデータ構造)に変換します。このツールは高速で、優れたインターフェイスも提供します。全体として、これは非常に強力なライブラリであり、HTMLスクレイピングの多数のニーズに対応します。

Nokogiriは、HTMLの解析だけでなく使用できます。 XMLも公正なゲームです。ロードするドキュメントをトラバースするためのXMLパス言語とCSSインターフェースの両方のオプションを提供します。 XMLパス言語(略してXPath)はクエリ言語です。

これにより、XMLドキュメントからノードを選択できます。 CSSセレクターは、おそらく初心者にはなじみがあります。作成するスタイルと同様に、CSSセレクターを使用すると、抽出対象のページの特定のセクションを非常に簡単にターゲットにできます。特定の目的地をターゲットにするときは、ノコギリに自分が何を求めているかを知らせる必要があります。

ページ

常に最初に必要なのは、関心のある実際のページをフェッチすることです。解析するNokogiriドキュメントの種類(たとえば、XMLまたはHTML)を指定します。

Nokogiri::XML

Nokogiri::HTML

some_scraper.rb

require "nokogiri"

require "open-uri"

page = Nokogiri::XML(File.open("some.xml"))

page = Nokogiri::HTML(File.open("some.html"))

Nokogiri:XML およびNokogiri:HTML IOオブジェクトまたはStringオブジェクトを取ることができます。上記で起こることは簡単です。これにより、open-uriを使用して、指定されたページが開き、フェッチされます。 次に、その構造、XML、またはHTMLを新しいNokogiriドキュメントにロードします。 XMLは、初心者が頻繁に扱う必要のあるものではありません。

したがって、今のところHTML解析に焦点を当てることをお勧めします。なぜopen-uri ? Ruby標準ライブラリのこのモジュールを使用すると、大騒ぎせずにサイトを取得できます。 IOオブジェクトは公正なゲームであるため、open-uriを簡単に使用できます。 。

API

小さな例でこれを実践してみましょう:

at_css

some_podcast_scraper.rb

require 'nokogiri'

require "open-uri"

url = 'https://betweenscreens.fm/'

page = Nokogiri::HTML(open(url))

header = page.at_css("h2.post-title")

title = header.text

puts "This is the raw header of the latest episode: #{header}"

puts "This is the title of the latest episode: #{title}"

ここで行ったことは、通常はWebスクレイピングに関連するすべてのステップをマイクロレベルで表したものです。必要なURLと取得する必要のあるサイトを決定し、それらを新しいNokogiriドキュメントに読み込みます。次に、そのページを開き、特定のセクションをターゲットにします。

ここでは、最新のエピソードのタイトルだけを知りたかったのです。 at_cssを使用する h2.post-titleのメソッドとCSSセレクター 抽出ポイントをターゲットにするために必要なのはそれだけでした。ただし、この方法では、この特異な要素のみをスクレイプします。これにより、セレクター全体が得られます。これは、ほとんどの場合、必要なものとは異なります。したがって、textを介して、このノードの内部テキスト部分のみを抽出します。 方法。比較のために、以下のヘッダーとテキストの両方の出力を確認できます。

出力

This is the raw title of the latest episode: <h2 class="post-title"><a href="episodes/142/">David Heinemeier Hansson</a></h2>

This is the title of the latest episode: David Heinemeier Hansson

この例のアプリケーションは非常に限られていますが、すべての要素、理解する必要のあるすべてのステップが含まれています。これがいかにシンプルかはクールだと思います。この例からは明らかではないかもしれないので、このツールがどれほど強力であるかを指摘したいと思います。 Nokogiriスクリプトで他に何ができるか見てみましょう。

注意!

初心者で、これに必要なHTMLをターゲットにする方法がわからない場合は、オンラインで検索して、ブラウザでウェブサイトのコンテンツを検査する方法を見つけることをお勧めします。基本的に、すべての主要なブラウザは、このプロセスを最近非常に簡単にします。

Chromeでは、ウェブサイトの要素を右クリックして、検査オプションを選択するだけです。これにより、ブラウザの下部に小さなウィンドウが開き、サイトのDOMのX線写真のようなものが表示されます。他にもたくさんのオプションがあります。自分自身を教育するために、Googleで時間を過ごすことをお勧めします。これは賢く過ごす時間です!

css

css メソッドは、選択した単一の要素だけでなく、ページの検索条件に一致する要素を提供します。かなりきちんとしていて簡単です!

some_scraper.rb

require 'nokogiri'

require "open-uri"

url = 'https://betweenscreens.fm/'

page = Nokogiri::HTML(open(url))

headers = page.css("h2.post-title")

headers.each do |header|
  puts "This is the raw title of the latest episode: #{header}"
end

headers.each do |header|
  puts "This is the title of the latest episode: #{header.text}"
end

出力

This is the raw title of the latest episode: <h2 class="post-title"><a href="episodes/142/">David Heinemeier Hansson</a></h2>
This is the raw title of the latest episode: <h2 class="post-title"><a href="episodes/141/">Zach Holman</a></h2>
This is the raw title of the latest episode: <h2 class="post-title"><a href="episodes/140/">Joel Glovier</a></h2>
This is the raw title of the latest episode: <h2 class="post-title"><a href="episodes/139/">João Ferreira</a></h2>
This is the raw title of the latest episode: <h2 class="post-title"><a href="episodes/138/">Corwin Harrell</a></h2>
This is the raw title of the latest episode: <h2 class="post-title"><a href="episodes/137/">Roberto Machado</a></h2>
This is the raw title of the latest episode: <h2 class="post-title"><a href="episodes/136/">James Edward Gray II</a></h2>

This is the title of the latest episode: David Heinemeier Hansson
This is the title of the latest episode: Zach Holman
This is the title of the latest episode: Joel Glovier
This is the title of the latest episode: João Ferreira
This is the title of the latest episode: Corwin Harrell
This is the title of the latest episode: Roberto Machado
This is the title of the latest episode: James Edward Gray II

この例の唯一の小さな違いは、最初に生のヘッダーを反復処理することです。また、textを使用して内部テキストを抽出しました 方法。のこぎりはページの最後で自動的に停止し、どこでも自動的にページネーションを追跡しようとはしません。

各エピソードの日付と字幕など、もう少し情報が必要だとします。上記の例を簡単に拡張できます。とにかく、このステップを段階的に実行することをお勧めします。小さな部分を機能させて、途中でさらに複雑さを加えます。

some_scraper.rb

require 'nokogiri'

require "open-uri"

url = 'https://betweenscreens.fm/'

page = Nokogiri::HTML(open(url))

articles = page.css("article.index-article")

articles.each do |article|
  header     = article.at_css("h2.post-title")
  date       = article.at_css(".post-date")
  subtitle   = article.at_css(".topic-list")

  puts "This is the raw header:    #{header}"
  puts "This is the raw date:      #{date}"
  puts "This is the raw subtitle:  #{subtitle}\n\n"
 
  puts "This is the text header:   #{header.text}"
  puts "This is the text date:     #{date.text}"
  puts "This is the text subtitle: #{subtitle.text}\n\n"
end

出力

This is the raw header: <h2 class="post-title"><a href="episodes/142/">David Heinemeier Hansson</a></h2>
This is the raw date: <span class="post-date">Oct 18 | 2016</span>
This is the raw subtitle: <h3 class="topic-list">Rails community | Tone | Technical disagreements | Community policing | Ungratefulness | No assholes allowed | Basecamp | Open source persona | Aspirations | Guarding motivations | Dealing with audiences | Pressure | Honesty | Diverse opinions | Small talk</h3>

This is the text header: David Heinemeier Hansson
This is the text date: Oct 18 | 2016
This is the text subtitle: Rails community | Tone | Technical disagreements | Community policing | Ungratefulness | No assholes allowed | Basecamp | Open source persona | Aspirations | Guarding motivations | Dealing with audiences | Pressure | Honesty | Diverse opinions | Small talk

This is the raw header: <h2 class="post-title"><a href="episodes/141/">Zach Holman</a></h2>
This is the raw date: <span class="post-date">Oct 12 | 2016</span>
This is the raw subtitle: <h3 class="topic-list">Getting Fired | Taboo | Transparency | Different Perspectives | Timing | Growth Stages | Employment &amp; Dating | Managers | At-will Employment | Tech Industry | Europe | Low hanging Fruits | Performance Improvement Plans | Meeting Goals | Surprise Firings | Firing Fast | Mistakes | Company Culture | Communication</h3>

This is the text header: Zach Holman
This is the text date: Oct 12 | 2016
This is the text subtitle: Getting Fired | Taboo | Transparency | Different Perspectives | Timing | Growth Stages | Employment & Dating | Managers | At-will Employment | Tech Industry | Europe | Low hanging Fruits | Performance Improvement Plans | Meeting Goals | Surprise Firings | Firing Fast | Mistakes | Company Culture | Communication

This is the raw header: <h2 class="post-title"><a href="episodes/140/">Joel Glovier</a></h2>
This is the raw date: <span class="post-date">Oct 10 | 2016</span>
This is the raw subtitle: <h3 class="topic-list">Digital Product Design | Product Design @ GitHub | Loving Design | Order &amp; Chaos | Drawing | Web Design | HospitalRun | Diversity | Startup Culture | Improving Lives | CURE International | Ember | Offline First | Hospital Information System | Designers &amp; Open Source</h3>

This is the text header: Joel Glovier
This is the text date: Oct 10 | 2016
This is the text subtitle: Digital Product Design | Product Design @ GitHub | Loving Design | Order & Chaos | Drawing | Web Design | HospitalRun | Diversity | Startup Culture | Improving Lives | CURE International | Ember | Offline First | Hospital Information System | Designers & Open Source

This is the raw header: <h2 class="post-title"><a href="episodes/139/">João Ferreira</a></h2>
This is the raw date: <span class="post-date">Aug 26 | 2015</span>
This is the raw subtitle: <h3 class="topic-list">Masters @ Work | Subvisual | Deadlines | Design personality | Design problems | Team | Pushing envelopes | Delightful experiences | Perfecting details | Company values</h3>

This is the text header: João Ferreira
This is the text date: Aug 26 | 2015
This is the text subtitle: Masters @ Work | Subvisual | Deadlines | Design personality | Design problems | Team | Pushing envelopes | Delightful experiences | Perfecting details | Company values

This is the raw header: <h2 class="post-title"><a href="episodes/138/">Corwin Harrell</a></h2>
This is the raw date: <span class="post-date">Aug 06 | 2015</span>
This is the raw subtitle: <h3 class="topic-list">Q&amp;A | 01 | University | Graphic design | Design setup | Sublime | Atom | thoughtbot | Working location | Collaboration &amp; pairing | Vim advocates | Daily routine | Standups | Clients | Coffee walks | Investment Fridays |</h3>

This is the text header: Corwin Harrell
This is the text date: Aug 06 | 2015
This is the text subtitle: Q&A | 01 | University | Graphic design | Design setup | Sublime | Atom | thoughtbot | Working location | Collaboration & pairing | Vim advocates | Daily routine | Standups | Clients | Coffee walks | Investment Fridays |

This is the raw header: <h2 class="post-title"><a href="episodes/137/">Roberto Machado</a></h2>
This is the raw date: <span class="post-date">Aug 03 | 2015</span>
This is the raw subtitle: <h3 class="topic-list">CEO @ Subvisual | RubyConf Portugal | Creators School | Consultancy | Company role models | Group Buddies | Portuguese startup | Rebranding | Technologies used | JS frameworks | TDD &amp; BDD | Startup mistakes | Culture of learning | Young entrepreneurs</h3>

This is the text header: Roberto Machado
This is the text date: Aug 03 | 2015
This is the text subtitle: CEO @ Subvisual | RubyConf Portugal | Creators School | Consultancy | Company role models | Group Buddies | Portuguese startup | Rebranding | Technologies used | JS frameworks | TDD & BDD | Startup mistakes | Culture of learning | Young entrepreneurs

This is the raw header: <h2 class="post-title"><a href="episodes/136/">James Edward Gray II</a></h2>
This is the raw date: <span class="post-date">Jul 30 | 2015</span>
This is the raw subtitle: <h3 class="topic-list">Screencasting | Less Code | Reading code | Getting unstuck | Rails’s codebase | CodeNewbie | Small examples | Future plans | PeepCode | Frequency &amp; pricing</h3>

This is the text header: James Edward Gray II
This is the text date: Jul 30 | 2015
This is the text subtitle: Screencasting | Less Code | Reading code | Getting unstuck | Rails’s codebase | CodeNewbie | Small examples | Future plans | PeepCode | Frequency & pricing

この時点で、すでにいくつかのデータを試してみることができます。好きなように構造化または肉屋にすることができます。上記は、私たちが持っているものを読みやすい形で示しているだけです。もちろん、textで正規表現を使用することで、これらのそれぞれをより深く掘り下げることができます。 方法。

実際のポッドキャストの問題を解決する際には、これについてさらに詳しく調べます。正規表現のクラスではありませんが、実際に動作しているものがいくつか表示されますが、脳出血を引き起こすほどの心配はありません。

属性

この段階で便利なのは、hrefを抽出することです。 個々のエピソードについても同様です。これ以上簡単なことはありません。

some_scraper.rb

require 'nokogiri'

require "open-uri"

url = 'https://betweenscreens.fm/'

page = Nokogiri::HTML(open(url))

articles = page.css("article.index-article")

articles.each do |article|
  header      = article.at_css("h2.post-title")
  date        = article.at_css(".post-date")
  subtitle    = article.at_css(".topic-list")
  link        = article.at_css("h2.post-title a")
  podcast_url = "https://betweenscreens.fm/"

  puts "This is the raw header:    #{header}"
  puts "This is the raw date:      #{date}"
  puts "This is the raw subtitle:  #{subtitle}"
  puts "This is the raw link:      #{link}\n\n"

  puts "This is the text header:   #{header.text}"
  puts "This is the text date:     #{date.text}"
  puts "This is the text subtitle: #{subtitle.text}"
  puts "This is the raw link:      #{podcast_url}#{link[:href]}\n\n"
end

ここで注意を払うべき最も重要なビットは[:href]です。 およびpodcast_url[:]にタグを付ける場合 ターゲットセレクターから属性を抽出するだけです。もう少し抽象化しましたが、以下でどのように機能するかをより明確に確認できます。

...

href = article.at_css("h2.post-title a")[:href]

...

完全で有用なURLを取得するために、ルートドメインを変数に保存し、エピソードごとに完全なURLを作成しました。

...

podcast_url = "https://betweenscreens.fm/"

puts "This is the raw link: #{podcast_url}#{link[:href]}\n\n"

...

出力を簡単に見てみましょう。

出力

This is the raw header:   <h2 class="post-title"><a href="episodes/143/">Jason Long</a></h2>
This is the raw date:     <span class="post-date">Oct 25 | 2016</span>
This is the raw subtitle: <h3 class="topic-list">Open source | Empathy | Lower barriers | Learning tool | Design contributions | Git website | Branding | GitHub | Neovim | Tmux | Design love | Knowing audiences | Showing work | Dribbble | Progressions | Ideas</h3>
This is the raw link:     <a href="episodes/143/">Jason Long</a>

This is the text header: Jason Long
This is the text date:   Oct 25 | 2016
This is the text subtitle: Open source | Empathy | Lower barriers | Learning tool | Design contributions | Git website | Branding | GitHub | Neovim | Tmux | Design love | Knowing audiences | Showing work | Dribbble | Progressions | Ideas
This is the href:     https://betweenscreens.fm/episodes/143/

This is the raw header:   <h2 class="post-title"><a href="episodes/142/">David Heinemeier Hansson</a></h2>
This is the raw date:     <span class="post-date">Oct 18 | 2016</span>
This is the raw subtitle: <h3 class="topic-list">Rails community | Tone | Technical disagreements | Community policing | Ungratefulness | No assholes allowed | Basecamp | Open source persona | Aspirations | Guarding motivations | Dealing with audiences | Pressure | Honesty | Diverse opinions | Small talk</h3>
This is the raw link:     <a href="episodes/142/">David Heinemeier Hansson</a>

This is the text header: David Heinemeier Hansson
This is the text date:   Oct 18 | 2016
This is the text subtitle: Rails community | Tone | Technical disagreements | Community policing | Ungratefulness | No assholes allowed | Basecamp | Open source persona | Aspirations | Guarding motivations | Dealing with audiences | Pressure | Honesty | Diverse opinions | Small talk
This is the href:     https://betweenscreens.fm/episodes/142/

This is the raw header:   <h2 class="post-title"><a href="episodes/141/">Zach Holman</a></h2>
This is the raw date:     <span class="post-date">Oct 12 | 2016</span>
This is the raw subtitle: <h3 class="topic-list">Getting Fired | Taboo | Transparency | Different Perspectives | Timing | Growth Stages | Employment &amp; Dating | Managers | At-will Employment | Tech Industry | Europe | Low hanging Fruits | Performance Improvement Plans | Meeting Goals | Surprise Firings | Firing Fast | Mistakes | Company Culture | Communication</h3>
This is the raw link:     <a href="episodes/141/">Zach Holman</a>

This is the text header: Zach Holman
This is the text date:   Oct 12 | 2016
This is the text subtitle: Getting Fired | Taboo | Transparency | Different Perspectives | Timing | Growth Stages | Employment & Dating | Managers | At-will Employment | Tech Industry | Europe | Low hanging Fruits | Performance Improvement Plans | Meeting Goals | Surprise Firings | Firing Fast | Mistakes | Company Culture | Communication
This is the href:     https://betweenscreens.fm/episodes/141/

This is the raw header:   <h2 class="post-title"><a href="episodes/140/">Joel Glovier</a></h2>
This is the raw date:     <span class="post-date">Oct 10 | 2016</span>
This is the raw subtitle: <h3 class="topic-list">Digital Product Design | Product Design @ GitHub | Loving Design | Order &amp; Chaos | Drawing | Web Design | HospitalRun | Diversity | Startup Culture | Improving Lives | CURE International | Ember | Offline First | Hospital Information System | Designers &amp; Open Source</h3>
This is the raw link:     <a href="episodes/140/">Joel Glovier</a>

This is the text header: Joel Glovier
This is the text date:   Oct 10 | 2016
This is the text subtitle: Digital Product Design | Product Design @ GitHub | Loving Design | Order & Chaos | Drawing | Web Design | HospitalRun | Diversity | Startup Culture | Improving Lives | CURE International | Ember | Offline First | Hospital Information System | Designers & Open Source
This is the href:     https://betweenscreens.fm/episodes/140/

This is the raw header:   <h2 class="post-title"><a href="episodes/139/">João Ferreira</a></h2>
This is the raw date:     <span class="post-date">Aug 26 | 2015</span>
This is the raw subtitle: <h3 class="topic-list">Masters @ Work | Subvisual | Deadlines | Design personality | Design problems | Team | Pushing envelopes | Delightful experiences | Perfecting details | Company values</h3>
This is the raw link:     <a href="episodes/139/">João Ferreira</a>

This is the text header: João Ferreira
This is the text date:   Aug 26 | 2015
This is the text subtitle: Masters @ Work | Subvisual | Deadlines | Design personality | Design problems | Team | Pushing envelopes | Delightful experiences | Perfecting details | Company values
This is the href:     https://betweenscreens.fm/episodes/139/

This is the raw header:   <h2 class="post-title"><a href="episodes/138/">Corwin Harrell</a></h2>
This is the raw date:     <span class="post-date">Aug 06 | 2015</span>
This is the raw subtitle: <h3 class="topic-list">Q&amp;A | 01 | University | Graphic design | Design setup | Sublime | Atom | thoughtbot | Working location | Collaboration &amp; pairing | Vim advocates | Daily routine | Standups | Clients | Coffee walks | Investment Fridays |</h3>
This is the raw link:     <a href="episodes/138/">Corwin Harrell</a>

This is the text header: Corwin Harrell
This is the text date:   Aug 06 | 2015
This is the text subtitle: Q&A | 01 | University | Graphic design | Design setup | Sublime | Atom | thoughtbot | Working location | Collaboration & pairing | Vim advocates | Daily routine | Standups | Clients | Coffee walks | Investment Fridays |
This is the href:     https://betweenscreens.fm/episodes/138/

This is the raw header:   <h2 class="post-title"><a href="episodes/137/">Roberto Machado</a></h2>
This is the raw date:     <span class="post-date">Aug 03 | 2015</span>
This is the raw subtitle: <h3 class="topic-list">CEO @ Subvisual | RubyConf Portugal | Creators School | Consultancy | Company role models | Group Buddies | Portuguese startup | Rebranding | Technologies used | JS frameworks | TDD &amp; BDD | Startup mistakes | Culture of learning | Young entrepreneurs</h3>
This is the raw link:     <a href="episodes/137/">Roberto Machado</a>

This is the text header: Roberto Machado
This is the text date:   Aug 03 | 2015
This is the text subtitle: CEO @ Subvisual | RubyConf Portugal | Creators School | Consultancy | Company role models | Group Buddies | Portuguese startup | Rebranding | Technologies used | JS frameworks | TDD & BDD | Startup mistakes | Culture of learning | Young entrepreneurs
This is the href:     https://betweenscreens.fm/episodes/137/

きちんとね。 [:class]を抽出するために同じことを行うことができます セレクターの。

require 'nokogiri'

require "open-uri"

url = 'https://betweenscreens.fm/'

page = Nokogiri::HTML(open(url))

body_classes = page.at_css("body")[:class]

そのノードに複数のクラスがある場合は、それらすべてのリストが表示されます。

ノードナビゲーション

  • 子供
  • previous_sibling
  • next_sibling

私たちはCSSやjQueryでツリー構造を扱うことに慣れています。 Nokogiriがそのようなツリー内を移動するための便利なAPIを提供していなかったら、それは苦痛でしょう。

some_scraper.rb

require 'nokogiri'

require "open-uri"

url = 'https://betweenscreens.fm/'

page = Nokogiri::HTML(open(url))

header = page.at_css("h2.post-title")
header_children = page.at_css("h2.post-title").children
header_parent = page.at_css("h2.post-title").parent
header_prev_sibling = page.at_css("h2.post-title").previous_sibling

puts "#{header}\n\n"
puts "#{header_children}\n\n"
puts "#{header_parent}\n\n"
puts "#{header_prev_sibling}\n\n"

出力

#header
<h2 class="post-title"><a href="episodes/143/">Jason Long</a></h2>

#header_children
<a href="episodes/143/">Jason Long</a>

#header_parent
<article class="index-article">
  <span class="post-date">Oct 25 | 2016</span><h2 class="post-title"><a href="episodes/143/">Jason Long</a></h2>
    <h3 class="topic-list">Open source | Empathy | Lower barriers | Learning tool | Design contributions | Git website | Branding | GitHub | Neovim | Tmux | Design love | Knowing audiences | Showing work | Dribbble | Progressions | Ideas</h3>
    <div class="soundcloud-player-small">  
    </div>
</article>

#header_previous_sibling
<span class="post-date">Oct 25 | 2016</span>

ご覧のとおり、これは非常に強力な機能です。特に、.parentを確認した場合はなおさらです。 一度に集めることができました。多数のノードを手動で定義する代わりに、それらをまとめて収集することができます。

より複雑なトラバーサルのためにそれらをチェーンすることもできます。もちろん、これは好きなだけ複雑にすることができますが、物事を単純にするように注意します。それはすぐに少し扱いに​​くく、理解するのが難しくなる可能性があります。 「シンプルに、愚かにしてください」ということを忘れないでください。

...

header_parent_parent = page.at_css("h2.post-title").parent.parent
header_prev_sibling_parent_children = page.at_css("h2.post-title").previous_sibling.parent.children

...

some_scraper.rb

require 'nokogiri'

require "open-uri"

url = 'https://betweenscreens.fm/'

page = Nokogiri::HTML(open(url))

header = page.at_css("h2.post-title")
header_prev_sibling_children = page.at_css("h2.post-title").previous_sibling.children
header_parent_parent = page.at_css("h2.post-title").parent.parent
header_prev_sibling_parent = page.at_css("h2.post-title").previous_sibling.parent
header_prev_sibling_parent_children = page.at_css("h2.post-title").previous_sibling.parent.children

puts "#{header}\n\n"
puts "#{header_prev_sibling_children}\n\n"
puts "#{header_parent_parent}\n\n"
puts "#{header_prev_sibling_parent}\n\n"
puts "#{header_prev_sibling_parent_children}\n\n"

出力

#header
<h2 class="post-title"><a href="episodes/143/">Jason Long</a></h2>

#header_previous_sibling_children
Oct 25 | 2016

#header_parent_parent
<li>
  <article class="index-article">
  <span class="post-date">Oct 25 | 2016</span><h2 class="post-title"><a href="episodes/143/">Jason Long</a></h2>
    <h3 class="topic-list">Open source | Empathy | Lower barriers | Learning tool | Design contributions | Git website | Branding | GitHub | Neovim | Tmux | Design love | Knowing audiences | Showing work | Dribbble | Progressions | Ideas</h3>
    <div class="soundcloud-player-small">  
    </div>
  </article>
</li>

#header_previous_sibling_parent
<article class="index-article">
  <span class="post-date">Oct 25 | 2016</span><h2 class="post-title"><a href="episodes/143/">Jason Long</a></h2>
    <h3 class="topic-list">Open source | Empathy | Lower barriers | Learning tool | Design contributions | Git website | Branding | GitHub | Neovim | Tmux | Design love | Knowing audiences | Showing work | Dribbble | Progressions | Ideas</h3>
    <div class="soundcloud-player-small">  
    </div>
</article>

#header_previous_sibling_parent_children
  <span class="post-date">Oct 25 | 2016</span><h2 class="post-title"><a href="episodes/143/">Jason Long</a></h2>
    <h3 class="topic-list">Open source | Empathy | Lower barriers | Learning tool | Design contributions | Git website | Branding | GitHub | Neovim | Tmux | Design love | Knowing audiences | Showing work | Dribbble | Progressions | Ideas</h3>
    <div class="soundcloud-player-small">  
    </div>

Final Thoughts

Nokogiri is not a huge library, but it has a lot to offer. I recommend you play with what you have learned thus far and expand your knowledge through its documentation when you hit a wall. But don’t get yourself into trouble!

This little intro should get you well on your way to understanding what you can do and how it works. I hope you will explore it a bit more on your own and have some fun with it. As you will find out on your own, it’s a rich tool that keeps on giving.


  1. iPhone で Web ブラウザを更新する方法

    iPhone でお気に入りの Web ブラウザーを更新すると、新しい機能、パフォーマンスの向上、およびバグ修正にアクセスできるようになります。最新のブラウザーは、インターネットをナビゲートする際のプライバシーとセキュリティの向上にもつながります。 しかし、Safari Web ブラウザーや、Google Chrome や Mozilla Firefox などのサードパーティの代替ブラウザーの最新の更新プログラムをどのようにインストールすればよいでしょうか? iPhone で Web ブラウザーを新しいバージョンに更新する方法については、以下をお読みください。以下の同じ方法は、iPod t

  2. ブラウザはどの程度非公開にする必要がありますか?

    ブログのまとめ – Web ブラウザを選択するとき、そのセキュリティとプライバシー機能に注意を払いますか?ウェブブラウザも私たちのデータを盗むことができることをご存知ですか?このブログですべてを読んで、ブラウザを非公開にする必要があることを確認してください。 ブラウザを使用すると、インターネットを閲覧できます。私たちは、疑わしい Web ページにアクセスしないことが安全だと考えているだけです。ただし、ブラウザのリークや、ターゲットを絞った広告に使用されている情報に関する一般的なニュースは新しいものではありません。では、Web ブラウザーは私たちにとってどの程度安全なのでしょうか?これは、今