最初のWebスクレイパーの構築、パート3
Webスクレイパーの構築に関するこのシリーズへようこそ。このチュートリアルでは、自分のポッドキャストサイトからデータをスクレイピングする例を紹介します。データを抽出する方法、ヘルパーメソッドとユーティリティメソッドがどのように仕事を遂行するか、すべてのパズルのピースがどのように組み合わされるかについて詳しく説明します。
トピック
- ポッドキャストをスクレイピングする
- こじ開ける
- スクレーパー
- ヘルパーメソッド
- 投稿を書く
ポッドキャストのスクレイピング
これまでに学んだことを実践してみましょう。さまざまな理由で、ポッドキャストの再設計を行いました。画面は長い間延期されていました。朝起きたときに悲鳴を上げる問題がありました。そこで、Middlemanで構築され、GitHubPagesでホストされるまったく新しい静的サイトをセットアップすることにしました。
Middlemanのブログを自分のニーズに合わせて調整した後、新しいデザインにかなりの時間を費やしました。あとは、データベースを利用したSinatraアプリからコンテンツをインポートするだけだったので、既存のコンテンツをスクレイピングして新しい静的サイトに転送する必要がありました。
友人のNokogiriとMechanizeに任せて仕事をしてもらうことができたので、これを手作業でシュマック方式で行うことは、テーブルにはありませんでした。質問すらありませんでした。あなたの前にあるのは、それほど複雑ではありませんが、ウェブスクレイピングの初心者にとって教育的であるはずのいくつかの興味深いひねりを提供する、適度に小さなスクレイピングジョブです。
以下は私のポッドキャストからの2つのスクリーンショットです。
スクリーンショットの古いポッドキャスト
スクリーンショットの新しいポッドキャスト
達成したいことを分解してみましょう。 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&auto_play=false&hide_related=false&show_comments=false&show_user=true&show_reposts=false&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ステップずつ実行し、すぐにクリックしなくてもイライラしないでください。これはほとんどの人にとって正常であるだけでなく、予想されることです。それは旅の一部です。ハッピースクレイピング!
-
iPhone で Web ブラウザを更新する方法
iPhone でお気に入りの Web ブラウザーを更新すると、新しい機能、パフォーマンスの向上、およびバグ修正にアクセスできるようになります。最新のブラウザーは、インターネットをナビゲートする際のプライバシーとセキュリティの向上にもつながります。 しかし、Safari Web ブラウザーや、Google Chrome や Mozilla Firefox などのサードパーティの代替ブラウザーの最新の更新プログラムをどのようにインストールすればよいでしょうか? iPhone で Web ブラウザーを新しいバージョンに更新する方法については、以下をお読みください。以下の同じ方法は、iPod t
-
ブラウザはどの程度非公開にする必要がありますか?
ブログのまとめ – Web ブラウザを選択するとき、そのセキュリティとプライバシー機能に注意を払いますか?ウェブブラウザも私たちのデータを盗むことができることをご存知ですか?このブログですべてを読んで、ブラウザを非公開にする必要があることを確認してください。 ブラウザを使用すると、インターネットを閲覧できます。私たちは、疑わしい Web ページにアクセスしないことが安全だと考えているだけです。ただし、ブラウザのリークや、ターゲットを絞った広告に使用されている情報に関する一般的なニュースは新しいものではありません。では、Web ブラウザーは私たちにとってどの程度安全なのでしょうか?これは、今