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

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

Webスクレイパーの構築に関するこのシリーズへようこそ。このチュートリアルでは、自分のポッドキャストサイトからデータをスクレイピングする例を紹介します。データを抽出する方法、ヘルパーメソッドとユーティリティメソッドがどのように仕事を遂行するか、すべてのパズルのピースがどのように組み合わされるかについて詳しく説明します。

トピック

  • ポッドキャストをスクレイピングする
  • こじ開ける
  • スクレーパー
  • ヘルパーメソッド
  • 投稿を書く

ポッドキャストのスクレイピング

これまでに学んだことを実践してみましょう。さまざまな理由で、ポッドキャストの再設計を行いました。画面は長い間延期されていました。朝起きたときに悲鳴を上げる問題がありました。そこで、Middlemanで構築され、GitHubPagesでホストされるまったく新しい静的サイトをセットアップすることにしました。

Middlemanのブログを自分のニーズに合わせて調整した後、新しいデザインにかなりの時間を費やしました。あとは、データベースを利用したSinatraアプリからコンテンツをインポートするだけだったので、既存のコンテンツをスクレイピングして新しい静的サイトに転送する必要がありました。

友人のNokogiriとMechanizeに任せて仕事をしてもらうことができたので、これを手作業でシュマック方式で行うことは、テーブルにはありませんでした。質問すらありませんでした。あなたの前にあるのは、それほど複雑ではありませんが、ウェブスクレイピングの初心者にとって教育的であるはずのいくつかの興味深いひねりを提供する、適度に小さなスクレイピングジョブです。

以下は私のポッドキャストからの2つのスクリーンショットです。

スクリーンショットの古いポッドキャスト

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

スクリーンショットの新しいポッドキャスト

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

達成したいことを分解してみましょう。 21のページ化されたインデックスサイトにまたがる139のエピソードから次のデータを抽出したいと思います。

  • タイトル
  • インタビュイー
  • トピックリストのあるサブヘッダー
  • 各エピソードのSoundCloudトラック番号
  • 日付
  • エピソード番号
  • ショーノートのテキスト
  • ショーノートからのリンク

ページネーションを繰り返し、Mechanizeにエピソードのすべてのリンクをクリックさせます。次の詳細ページでは、必要な上記のすべての情報を見つけることができます。そのスクレイピングされたデータを使用して、各エピソードのマークダウンファイルの前書きと「本文」を入力します。

以下に、抽出したコンテンツを使用して新しいマークダウンファイルを作成する方法のプレビューを示します。これにより、私たちの前にあるスコープについての良いアイデアが得られると思います。これは、小さなスクリプトの最後のステップを表しています。心配しないでください。詳しく説明します。

def compose_markdown

def compose_markdown(options={})
<<-HEREDOC
--- 
title: #{options[:interviewee]}
interviewee: #{options[:interviewee]}
topic_list: #{options[:title]}
tags: #{options[:tags]}
soundcloud_id: #{options[:sc_id]}
date: #{options[:date]}
episode_number: #{options[:episode_number]}
---

#{options[:text]}
HEREDOC
end

また、古いサイトでは再生できなかったトリックをいくつか追加したいと思いました。カスタマイズされた包括的なタグ付けシステムを導入することは、私にとって非常に重要でした。私はリスナーに深い発見ツールを持たせたかったのです。したがって、すべてのインタビュイーにタグが必要であり、サブヘッダーもタグに分割しました。最初のシーズンだけで139話を制作したので、コンテンツの量がわかりにくくなる時期に備えてサイトを準備しなければなりませんでした。インテリジェントに配置された推奨事項を備えた深いタグ付けシステムがその方法でした。これにより、サイトを軽量かつ高速に保つことができました。

私のサイトのコンテンツをスクレイピングするための完全なコードを見てみましょう。周りを見回して、何が起こっているのか全体像を把握してみてください。私はあなたが物事の初心者の側にいることを期待しているので、私は抽象化しすぎないようにし、明快さの側で誤りを犯しました。コードの明確化を支援することを目的としたリファクタリングをいくつか行いましたが、この記事を読み終えたときに試してみるために、骨に少し肉を残しました。結局のところ、質の高い学習は、自分でコードを読んだり、いじったりするだけではありません。

その過程で、目の前のコードをどのように改善できるかを考え始めることを強くお勧めします。これが、この記事の最後の最後のタスクになります。私からのちょっとしたヒント:大きなメソッドを小さなメソッドに分割することは、常に良い出発点です。コードがどのように機能するかを理解したら、そのリファクタリングに焦点を当てて楽しい時間を過ごす必要があります。

私はすでに、たくさんのメソッドを小さな焦点を絞ったヘルパーに抽出することから始めました。コードの臭いとそのリファクタリングについての私の以前の記事から学んだことを簡単に適用できるはずです。これが今でも頭に浮かぶ場合でも、心配しないでください。私たちは皆そこにいます。そのままにしておくと、ある時点で物事がより速くクリックし始めます。

完全なコード

require 'Mechanize'
require 'Pry'
require 'date'

# Helper Methods

# (Extraction Methods)

def extract_interviewee(detail_page)
  interviewee_selector = '.episode_sub_title span'
  detail_page.search(interviewee_selector).text.strip
end

def extract_title(detail_page)
  title_selector = ".episode_title"
  detail_page.search(title_selector).text.gsub(/[?#]/, '')
end

def extract_soundcloud_id(detail_page)
  sc = detail_page.iframes_with(href: /soundcloud.com/).to_s
  sc.scan(/\d{3,}/).first
end

def extract_shownotes_text(detail_page)
  shownote_selector = "#shownote_container > p"
  detail_page.search(shownote_selector)
end

def extract_subtitle(detail_page)
  subheader_selector = ".episode_sub_title"
  detail_page.search(subheader_selector).text
end

def extract_episode_number(episode_subtitle)
  number = /[#]\d*/.match(episode_subtitle)
  clean_episode_number(number)
end

# (Utility Methods)

def clean_date(episode_subtitle)
  string_date = /[^|]*([,])(.....)/.match(episode_subtitle).to_s
  Date.parse(string_date)
end

def build_tags(title, interviewee)
  extracted_tags = strip_pipes(title)
  "#{interviewee}"+ ", #{extracted_tags}"
end

def strip_pipes(text)
  tags = text.tr('|', ',')
  tags = tags.gsub(/[@?#&]/, '')
  tags.gsub(/[w\/]{2}/, 'with')
end

def clean_episode_number(number)
  number.to_s.tr('#', '')
end

def dasherize(text)
  text.lstrip.rstrip.tr(' ', '-')
end

def extract_data(detail_page)
  interviewee = extract_interviewee(detail_page)
  title = extract_title(detail_page)
  sc_id = extract_soundcloud_id(detail_page)
  text = extract_shownotes_text(detail_page)
  episode_subtitle = extract_subtitle(detail_page)
  episode_number = extract_episode_number(episode_subtitle)
  date = clean_date(episode_subtitle)
  tags = build_tags(title, interviewee)

  options = {
    interviewee:    interviewee,
    title:          title,
    sc_id:          sc_id,
    text:           text,
    tags:           tags,
    date:           date,
    episode_number: episode_number
  }
end

def compose_markdown(options={})
<<-HEREDOC
--- 
title: #{options[:interviewee]}
interviewee: #{options[:interviewee]}
topic_list: #{options[:title]}
tags: #{options[:tags]}
soundcloud_id: #{options[:sc_id]}
date: #{options[:date]}
episode_number: #{options[:episode_number]}
---

#{options[:text]}
HEREDOC
end

def write_page(link)
  detail_page = link.click

  extracted_data = extract_data(detail_page)

  markdown_text = compose_markdown(extracted_data)
  date = extracted_data[:date]
  interviewee = extracted_data[:interviewee]
  episode_number = extracted_data[:episode_number]

  File.open("#{date}-#{dasherize(interviewee)}-#{episode_number}.html.erb.md", 'w') { |file| file.write(markdown_text) }
end

def scrape
  link_range = 1
  agent ||= Mechanize.new

  until link_range == 21
    page = agent.get("https://between-screens.herokuapp.com/?page=#{link_range}")
    link_range += 1

    page.links[2..8].map do |link|
      write_page(link)
    end
  end
end

scrape

「Nokogiri」が必要なのはなぜですか ? Mechanizeは、スクレイピングのすべてのニーズを提供します。前回の記事で説明したように、MechanizeはNokogiriの上に構築されており、コンテンツを抽出することもできます。ただし、その上に構築する必要があるため、最初の記事でその宝石をカバーすることが重要でした。

こじ開け

まず最初に。ここでコードに飛び込む前に、コードがすべてのステップで期待どおりに機能するかどうかを効率的に確認する方法を示す必要があると思いました。お気づきのとおり、ミックスに別のツールを追加しました。とりわけ、 Pry デバッグには本当に便利です。

Pry.start(binding)を配置した場合 コードのどこにいても、その時点でアプリケーションを検査できます。アプリケーションの特定のポイントでオブジェクトをこじ開けることができます。これは、自分の足でつまずくことなく、アプリケーションを段階的に実行するのに非常に役立ちます。たとえば、 write_pageの直後に配置しましょう 機能し、 linkかどうかを確認します 私たちが期待するものです。

こじ開け

...

def scrape
  link_range = 1
  agent ||= Mechanize.new

  until link_range == 21
    page = agent.get("https://between-screens.herokuapp.com/?page=#{link_range}")
    link_range += 1

    page.links[2..8].map do |link|
      write_page(link)
      Pry.start(binding)
    end
  end
end

...

スクリプトを実行すると、次のようになります。

出力

»$ ruby noko_scraper.rb

    321: def scrape
    322:     link_range = 1
    323:     agent ||= Mechanize.new
    324: 
    326:   until link_range == 21
    327:     page = agent.get("https://between-screens.herokuapp.com/?page=#{link_range}")
    328:     link_range += 1
    329: 
    330:     page.links[2..8].map do |link|
    331:       write_page(link)
 => 332:     Pry.start(binding)
    333:     end
    334:   end
    335: end

[1] pry(main)>

次に、 linkを要求すると オブジェクトの場合、他の実装の詳細に進む前に、正しい方向に進んでいるかどうかを確認できます。

ターミナル

[2] pry(main)> link
=> #<Mechanize::Page::Link
 "Masters @ Work | Subvisual | Deadlines | Design personality | Design problems | Team | Pushing envelopes | Delightful experiences | Perfecting details | Company values"
 "/episodes/139">

必要なもののように見えます。よかった、先に進むことができます。アプリケーション全体を段階的に実行することは、迷子にならないようにし、アプリケーションがどのように機能するかを本当に理解するための重要なプラクティスです。 Pryについては、少なくとももう1つの完全な記事が必要になるため、ここではこれ以上詳しく説明しません。標準のIRBシェルの代わりに使用することをお勧めします。メインタスクに戻ります。

スクレーパー

パズルのピースに慣れてきたので、パズルのピースを1つずつ調べて、いくつかの興味深い点をあちこちで明らかにすることをお勧めします。中心的な部分から始めましょう。

podcast_scraper.rb

...

def write_page(link)
  detail_page = link.click
  
  extracted_data = extract_data(detail_page)

  markdown_text = compose_markdown(extracted_data)
  date = extracted_data[:date]
  interviewee = extracted_data[:interviewee]
  episode_number = extracted_data[:episode_number]

  file_name = "#{date}-#{dasherize(interviewee)}-#{episode_number}.html.erb.md" 

  File.open(file_name, 'w') { |file| file.write(markdown_text) }
end

def scrape
  link_range = 1
  agent ||= Mechanize.new

  until link_range == 21
    page = agent.get("https://between-screens.herokuapp.com/?page=#{link_range}")
    link_range += 1

    page.links[2..8].map do |link|
      write_page(link)
    end
  end
end

...

scrapeで何が起こるか 方法?まず、古いポッドキャストのすべてのインデックスページをループします。新しいサイトはすでにbetweenscreens.fmでオンラインになっているため、Herokuアプリの古いURLを使用しています。ループする必要のあるエピソードが20ページありました。

link_rangeを介してループを区切りました 変数。ループごとに更新しました。ページネーションを通過するのは、各ページのURLでこの変数を使用するのと同じくらい簡単でした。シンプルで効果的。

defスクレイプ

page = agent.get("https://between-screens.herokuapp.com/?page=#{link_range}")

次に、スクレイプするエピソードがさらに8つある新しいページを取得するたびに、 page.linksを使用します。 クリックしたいリンクを特定し、各エピソードの詳細ページに進みます。さまざまなリンク(links [2..8] )を使用することにしました )すべてのページで一貫していたため。また、各インデックスページから必要なリンクをターゲットにする最も簡単な方法でもありました。ここでCSSセレクターをいじくり回す必要はありません。

次に、詳細ページへのリンクを write_pageにフィードします 方法。これは、ほとんどの作業が行われる場所です。そのリンクを取得してクリックし、詳細ページに進んでデータの抽出を開始します。そのページには、新しいサイトの新しいマークダウンエピソードを作成するために必要なすべての情報があります。

def write_page

extracted_data = extract_data(detail_page)

def extract_data

def extract_data(detail_page)
  interviewee = extract_interviewee(detail_page)
  title = extract_title(detail_page)
  sc_id = extract_soundcloud_id(detail_page)
  text = extract_shownotes_text(detail_page)
  episode_subtitle = extract_subtitle(detail_page)
  episode_number = extract_episode_number(episode_subtitle)
  date = clean_date(episode_subtitle)
  tags = build_tags(title, interviewee)

  options = {
    interviewee:    interviewee,
    title:          title,
    sc_id:          sc_id,
    text:           text,
    tags:           tags,
    date:           date,
    episode_number: episode_number
  }
end

上記のように、 detail_pageを使用します それにたくさんの抽出方法を適用します。 インタビュイーを抽出します 、 title sc_id text Episode_title 、および Episode_number 。私は、これらの抽出の責任を担当する集中的なヘルパーメソッドの束をリファクタリングしました。それらを簡単に見てみましょう。

ヘルパーメソッド

抽出方法

これらのヘルパーを抽出したのは、全体的にメソッドを小さくできるようになったためです。彼らの行動をカプセル化することも重要でした。コードも読みやすくなっています。それらのほとんどはdetail_pageを取ります 議論として、ミドルマンの投稿に必要な特定のデータを抽出します。

def extract_interviewee(detail_page)
  interviewee_selector = '.episode_sub_title span'
  detail_page.search(interviewee_selector).text.strip
end

ページで特定のセレクターを検索し、不要な空白のないテキストを取得します。

def extract_title(detail_page)
  title_selector = ".episode_title"
  detail_page.search(title_selector).text.gsub(/[?#]/, '')
end

タイトルを取得してを削除します および これらは、エピソードの投稿の前書きとうまく調和していないためです。以下のフロントマターの詳細。

def extract_soundcloud_id(detail_page)
  sc = detail_page.iframes_with(href: /soundcloud.com/).to_s
  sc.scan(/\d{3,}/).first
end

ここでは、ホストされているトラックのSoundCloudIDを抽出するためにもう少し努力する必要がありました。まず、 hrefを使用してMechanizeiframeが必要です。 soundcloud.comの スキャン用の文字列にします...

"[#<Mechanize::Page::Frame\n nil\n \"https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/221003494&amp;auto_play=false&amp;hide_related=false&amp;show_comments=false&amp;show_user=true&amp;show_reposts=false&amp;visual=true\">\n]"

次に、トラックIDの数字に正規表現を一致させます— soundcloud_id "221003494"

def extract_shownotes_text(detail_page)
  shownote_selector = "#shownote_container > p"
  detail_page.search(shownote_selector)
end

ショーノートの抽出も非常に簡単です。詳細ページでショーノートの段落を探すだけです。ここに驚きはありません。

def extract_subtitle(detail_page)
  subheader_selector = ".episode_sub_title"
  detail_page.search(subheader_selector).text
end

字幕からエピソード番号をきれいに抽出するための準備にすぎないことを除いて、同じことが字幕にも当てはまります。

def extract_episode_number(episode_subtitle)
  number = /[#]\d*/.match(episode_subtitle)
  clean_episode_number(number)
end

ここで、正規表現の別のラウンドが必要です。正規表現を適用する前後を見てみましょう。

Episode_subtitle

" João Ferreira  | 12  Minutes |  Aug 26, 2015 | Episode #139  "

番号

"#139"

きれいな番号が得られるまで、もう1ステップ。

def clean_episode_number(number)
  number.to_s.tr('#', '')
end

その番号をハッシュで取得します そしてそれを削除します。 Voilà、最初のエピソード番号 139 同様に抽出されます。すべてをまとめる前に、他のユーティリティメソッドも検討することをお勧めします。

ユーティリティメソッド

抽出ビジネスがすべて終わったら、クリーンアップを行う必要があります。マークダウンを作成するためのデータの準備はすでに開始できます。たとえば、 episode_subtitleをスライスします きれいな日付を取得してタグを作成するためにもう少し build_tagsを使用 方法。

def clean_date

def clean_date(episode_subtitle)
  string_date = /[^|]*([,])(.....)/.match(episode_subtitle).to_s
  Date.parse(string_date)
end

次のような日付を検索する別の正規表現を実行します:"2015年8月26日" 。ご覧のとおり、これはまだあまり役に立ちません。 string_dateから サブタイトルから取得するには、実際の Dateを作成する必要があります 物体。そうでなければ、ミドルマンの投稿を作成するのに役に立たないでしょう。

string_date

"  Aug 26, 2015"

したがって、その文字列を取得して Date.parseを実行します 。結果ははるかに有望に見えます。

日付

2015-08-26

def build_tags

def build_tags(title, interviewee)
  extracted_tags = strip_pipes(title)
  "#{interviewee}"+ ", #{extracted_tags}"
end

これにはtitleが必要です およびインタビュイー extract_data内に構築しました メソッドを使用して、すべてのパイプ文字とジャンクを削除します。パイプ文字をコンマ@に置き換えます 、 、および 空の文字列を使用し、最後に withの省略形を処理します 。

def strip_pipes

def strip_pipes(text)
  tags = text.tr('|', ',')
  tags = tags.gsub(/[@?#&]/, '')
  tags.gsub(/[w\/]{2}/, 'with')
end

最後に、インタビュー対象者の名前もタグリストに含め、各タグをコンマで区切ります。

"Masters @ Work | Subvisual | Deadlines | Design personality | Design problems | Team | Pushing envelopes | Delightful experiences | Perfecting details | Company values"

"João Ferreira, Masters  Work , Subvisual , Deadlines , Design personality , Design problems , Team , Pushing envelopes , Delightful experiences , Perfecting details , Company values"

これらの各タグは、そのトピックの投稿のコレクションへのリンクになります。これはすべて、 extract_data内で発生しました 方法。私たちがどこにいるのかをもう一度見てみましょう。

def extract_data

def extract_data(detail_page)
  interviewee = extract_interviewee(detail_page)
  title = extract_title(detail_page)
  sc_id = extract_soundcloud_id(detail_page)
  text = extract_shownotes_text(detail_page)
  episode_subtitle = extract_subtitle(detail_page)
  episode_number = extract_episode_number(episode_subtitle)
  date = clean_date(episode_subtitle)
  tags = build_tags(title, interviewee)

  options = {
    interviewee:    interviewee,
    title:          title,
    sc_id:          sc_id,
    text:           text,
    tags:           tags,
    date:           date,
    episode_number: episode_number
  }
end

ここで行う必要があるのは、抽出したデータを含むオプションハッシュを返すことだけです。このハッシュをcompose_markdownにフィードできます メソッド。これにより、新しいサイトに必要なファイルとしてデータを書き出す準備が整います。

投稿を書く

def compose_markdown

def compose_markdown(options={})
<<-HEREDOC
--- 
title: #{options[:interviewee]}
interviewee: #{options[:interviewee]}
topic_list: #{options[:title]}
tags: #{options[:tags]}
soundcloud_id: #{options[:sc_id]}
date: #{options[:date]}
episode_number: #{options[:episode_number]}
---

#{options[:text]}
HEREDOC
end

私のミドルマンサイトでポッドキャストエピソードを公開するために、私はそのブログシステムを再利用することを選びました。 「純粋な」ブログ投稿を作成する代わりに、iframeを介してSoundCloudでホストされているエピソードを表示するエピソードのショーノートを作成します。インデックスサイトでは、そのiframeとタイトルなどのみを表示します。

これが機能するために必要なフォーマットは、フロントマターと呼ばれるもので構成されています。これは基本的に、静的サイトのキー/値ストアです。それは私の古いSinatraサイトからの私のデータベースのニーズを置き換えています。

インタビュイーの名前、日付、SoundCloudトラックID、エピソード番号などのデータは、3つのダッシュの間にあります( --- )エピソードファイルの上に。以下に、質問、リンク、スポンサーなど、各エピソードのコンテンツを示します。

フロントマター

---
key: value
key: value
key: value
key: value
---

Episode content goes here.

compose_markdown内 メソッドでは、 HEREDOCを使用します ループする各エピソードのフロントマターを使用してそのファイルを作成します。このメソッドにフィードするオプションハッシュから、 extract_dataで収集したすべてのデータを抽出します ヘルパーメソッド。

def compose_markdown

...

<<-HEREDOC
--- 
title: #{options[:interviewee]}
interviewee: #{options[:interviewee]}
topic_list: #{options[:title]}
tags: #{options[:tags]}
soundcloud_id: #{options[:sc_id]}
date: #{options[:date]}
episode_number: #{options[:episode_number]}
---

#{options[:text]}
HEREDOC

...

これは、そこにある新しいポッドキャストエピソードの青写真です。これが私たちの目的です。おそらく、この特定の構文について疑問に思っているでしょう:#{options [:interviewee]} 。いつものように文字列で補間しますが、すでに <<-HEREDOC内にいるので 、二重引用符は省略できます。

自分自身を方向付けるために、私たちはまだ write_page内のループにいます 単一のエピソードのショーノートを含む詳細ページへのクリックされたリンクごとに機能します。次に行われるのは、このブループリントをファイルシステムに書き込む準備をすることです。つまり、ファイル名と構成された markdown_text を指定して、実際のエピソードを作成します。 。

その最後のステップでは、次の材料を準備する必要があります:日付、インタビュー対象者の名前、エピソード番号。さらに、 markdown_text もちろん、 compose_markdownから取得したものです 。

def write_page

...

markdown_text = compose_markdown(extracted_data)
date = extracted_data[:date]
interviewee = extracted_data[:interviewee]
episode_number = extracted_data[:episode_number]

file_name = "#{date}-#{dasherize(interviewee)}-#{episode_number}.html.erb.md" 

...

次に、 file_nameを取得するだけです。 およびmarkdown_text ファイルを書き込みます。

def write_page

...

File.open(file_name, 'w') { |file| file.write(markdown_text) }

...

これも分解しましょう。投稿ごとに、 2016-10-25-Avdi-Grimm-120のような特定の形式が必要です。 。日付で始まり、インタビュー対象者の名前とエピソード番号を含むファイルを書きたいです。

Middlemanが新しい投稿に期待する形式に一致させるために、インタビュー対象者の名前を取得し、それをヘルパーメソッドに通して dasherizeする必要がありました。 Avdi Grimmからの私の名前 Avdi-Grimmへ 。魔法はありませんが、一見の価値があります。

def dasherize

def dasherize(text)
  text.lstrip.rstrip.tr(' ', '-')
end

インタビュイー名のために削ったテキストから空白を削除し、AvdiとGrimmの間の空白をダッシュ​​に置き換えます。ファイル名の残りの部分は、文字列自体に破線で示されています: "date-interviewee-name-episodenumber"

def write_page

...

"#{date}-#{dasherize(interviewee)}-#{episode_number}.html.erb.md"

...

抽出されたコンテンツはHTMLサイトから直接取得されるため、 .mdを単純に使用することはできません。 または.markdown ファイル名拡張子として。 .html.erb.mdを使用することにしました 。スクレイピングせずに作成する今後のエピソードでは、 .html.erbを省略できます。 一部であり、 .mdのみが必要です 。

このステップの後、 scrapeのループ 関数が終了し、次のような1つのエピソードが必要になります。

2014-12-01-Avdi-Grimm-1.html.erb.md

--- 
title: Avdi Grimm
interviewee: Avdi Grimm
topic_list: What is Rake | Origins | Jim Weirich | Common use cases | Advantages of Rake
tags: Avdi Grimm, What is Rake , Origins , Jim Weirich , Common use cases , Advantages of Rake
soundcloud_id: 179619755
date: 2014-12-01
episode_number: 1
---

Questions:
- What is Rake?
- What can you tell us about the origins of Rake?
- What can you tell us about Jim Weihrich?
- What are the most common use cases for Rake?
- What are the most notable advantages of Rake?

Links:
In">https://www.youtube.com/watch?v=2ZHJSrF52bc">In memory of the great Jim Weirich
Rake">https://github.com/jimweirich/rake">Rake on GitHub
Jim">https://github.com/jimweirich">Jim Weirich on GitHub
Basic">https://www.youtube.com/watch?v=AFPWDzHWjEY">Basic Rake talk by Jim Weirich
Power">https://www.youtube.com/watch?v=KaEqZtulOus">Power Rake talk by Jim Weirich
Learn">https://devblog.avdi.org/2014/04/30/learn-advanced-rake-in-7-episodes/">Learn advanced Rake in 7 episodes - from Avdi Grimm ( free )
Avdi">https://about.avdi.org/">Avdi Grimm
Avdi Grimm’s screencasts: Ruby">https://www.rubytapas.com/">Ruby Tapas
Ruby">https://devchat.tv/ruby-rogues/">Ruby Rogues podcast with Avdi Grimm
Great ebook: Rake">https://www.amazon.com/Rake-Management-Essentials-Andrey-Koleshko/dp/1783280778">Rake Task Management Essentials fromhttps://twitter.com/ka8725"> Andrey Koleshko

もちろん、このスクレーパーは最後のエピソードから始まり、最初のエピソードまでループします。デモンストレーションの目的で、エピソード01は他のエピソードと同じくらい優れています。抽出したデータを前面に表示できます。

以前は、エピソード番号、日付、面接対象者の名前など、すべてが私のSinatraアプリのデータベースにロックされていました。これで、新しい静的ミドルマンサイトの一部になる準備が整いました。 2つのトリプルダッシュの下にあるものすべて( --- )はショーノートからのテキストです:主に質問とリンク。

最終的な考え

そして、これで完了です。私の新しいポッドキャストはすでに稼働しています。時間をかけてゼロから再設計できて本当に良かったです。今すぐ新しいエピソードを公開する方がはるかにクールです。新しいコンテンツの発見は、ユーザーにとってもスムーズになるはずです。

先に述べたように、これはあなたがいくつかの楽しみを持っているためにあなたのコードエディタに入る必要がある時です。このコードを取り、少し取り組んでください。それを簡単にする方法を見つけてください。コードをリファクタリングする機会がいくつかあります。

全体として、この小さな例が、新しいWebスクレイピングチョップで何ができるかについての良いアイデアを与えてくれることを願っています。もちろん、はるかに高度な課題を達成することもできます。これらのスキルを使用して、中小企業の機会がたくさんあると確信しています。

ただし、いつものように、一度に1ステップずつ実行し、すぐにクリックしなくてもイライラしないでください。これはほとんどの人にとって正常であるだけでなく、予想されることです。それは旅の一部です。ハッピースクレイピング!


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

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

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

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