効率的なWebスクレイピング入門:ブラウザの開発者コンソールとJavaScriptだけでデータを抽出・保存する方法
こんにちは、Praveen Dubeyです。少し前に、あるサイトからリンクをクロールし、そのページリンクをもとにSeleniumやPuppeteerを使ってデータを収集する必要がありました。しかし、そのサイトの構造が少々特殊だったため、いきなりSeleniumやNode.jsで始めることができませんでした。さらに困ったことに、サイト上のデータ量も膨大でした。そこで私は、まず全リンクを素早くクロールして収集し、その後それぞれのページの詳細データを取得するというアプローチを考える必要がありました。
そんなときに出会ったのが、ブラウザのConsole APIを活用するこのクールな手法です。これは単なるJavaScriptなので、ほとんどセットアップなしでどんなサイトでも使えます。
それでは、技術的な詳細を見ていきましょう。
全体像
ページ上のすべてのリンクをクロールするために、コンソールに小さなJavaScriptを書きました。このスクリプトはすべてのリンクをクロールし(ページネーションも処理するため1〜2時間かかります)、収集した全データをjsonファイルとして出力します。
ここで注意すべき点は、対象のウェブサイトがシングルページアプリケーション(SPA)のように動作することを確認する必要があるということです。複数ページをクロールしたい場合、ページが再読み込みされない仕組みでなければなりません。もしページが再読み込みされると、コンソールに入力したコードは消えてしまいます。
Mediumは一部のシナリオではページを更新しません。今回は例として、Mediumの記事をスクレイピングし、取得したデータをコンソールから自動的にファイルへ保存する流れを見てみましょう。
その前に、最終的な実行イメージをデモでご覧ください。
デモ画面
1. ブラウザからConsoleオブジェクトのインスタンスを取得する
// 新しいデータをログする前にコンソールをクリアするConsole API
console.API;
if (typeof console._commandLineAPI !== 'undefined') {
console.API = console._commandLineAPI; // Chrome用
} else if (typeof console._inspectorCommandLineAPI !== 'undefined') {
console.API = console._inspectorCommandLineAPI; // Safari用
} else if (typeof console.clear !== 'undefined') {
console.API = console;
}
このコードは、ユーザーが現在使用しているブラウザに応じてConsoleオブジェクトのインスタンスを取得するだけのものです。無視して、自分のブラウザ向けのインスタンスを直接代入しても構いません。
たとえばChromeを使っているなら、以下のコードだけで十分です。
if (typeof console._commandLineAPI !== 'undefined') {
console.API = console._commandLineAPI; // Chrome用
}
2. 基本のヘルパー関数(Junior Helper)を定義する
ここでは、ブラウザでMediumの記事を開いていることを前提とします。コードの6行目から12行目では、記事タイトル、クラップ数、ユーザー名、プロフィール画像URL、プロフィール説明文、記事の読了時間といった要素を抽出するためのDOM属性を定義しています。
これらはこの記事で紹介する基本的な項目ですが、さらに記事内のリンク抽出、画像の一括取得、埋め込みリンクの抽出などの要素を追加することもできます。
3. メインのヘルパー関数(Senior Helper)— いわば「獣」— を定義する
ページからさまざまな要素をクロールするので、それらをコレクションに保存していきます。このコレクションは、主要な関数のひとつに渡されます。
ここで定義するのがconsole.saveという関数です。この関数の役割は、渡されたデータをCSV/JSONファイルとして出力することです。
内部では、データをもとにBlobオブジェクトを作成します。Blobオブジェクトは、不変の生データをファイルのような形で表現するものです。BLOBは必ずしもJavaScriptネイティブの形式ではないデータを扱えます。
作成したBlobは<a>タグに紐付けられ、そのリンクに対してクリックイベントが発火される仕組みです。
以下は、小さなarrayをデータとして渡した場合のconsole.saveの簡単なデモです。
コードをつなぎ合わせる
これまでの要素をすべてまとめると、次の3つのパーツで構成されます。
- Console APIインスタンス
- 要素を抽出するヘルパー関数
- ファイルを作成するconsole.save関数
それでは、ブラウザでconsole.save()を実行し、データをファイルに保存してみましょう。Mediumの任意の記事を開き、ブラウザのコンソールでこのコードを実行してください。
ここまでは単一ページからのデータ抽出をデモしましたが、同じコードを少し修正すれば、パブリケーションのホームページから複数の記事をクロールすることもできます。たとえばfreeCodeCampの例を挙げると、ある記事から別の記事へ移動し、(ブラウザの戻るボタンを使って)パブリケーションのホームページへ戻っても、ページが再読み込みされません。
以下は、パブリケーションのホームページから複数記事を抽出するための最小限のコードです。
実際に、複数記事からプロフィールの説明文を取得する様子を見てみましょう。
この種のアプリケーションでは、一度データをスクレイピングしてしまえば、あとはconsole.save関数に渡すだけでファイルとして保存できます。
console.save関数はコンソールコードにすぐに組み込めて、データのファイル出力を手軽に行えます。コンソールを使ってスクレイピングしろと言っているわけではありませんが、CSSセレクタでのDOM操作に慣れている人にとっては、場合によっては断然速いアプローチになるでしょう。
コードはGitHubからダウンロードできます。
最後までお読みいただきありがとうございました!この記事が、あまりセットアップせずに素早くデータをスクレイピングするヒントになれば幸いです。気に入ったらクラップボタンを押してくださいね。質問がある方は、メール(praveend806 [at] gmail [dot] com)でお気軽にご連絡ください。
Consoleについてさらに学ぶためのリソース:
- Using the Console | Tools for Web Developers | Google Developers
Chrome DevToolsのJavaScriptコンソールの操作方法を学べます。(developers.google.com) - Browser Console | MDN Web Docs
ブラウザコンソールはウェブコンソールと似ていますが、単一のコンテンツタブではなくブラウザ全体に適用されます。(developer.mozilla.org) - Blob | MDN Web Docs
Blobオブジェクトは、不変の生データをファイルのような形で表現します。(developer.mozilla.org)
無料でプログラミングを学びましょう。freeCodeCampのオープンソースカリキュラムは、これまで4万人以上の人々を開発者としての仕事へと導いてきました。
-
危険なウェブサイトから身を守る!Chrome拡張機能「Tweaks Web Protection」の機能と使い方
インターネットという大海原を航海することには、毎日新しい知識に出会えるという大きな魅力があります。速報ニュース、友人の近況、面白い動画、音楽、往年の名作映画まで、デジタルの世界は自由に散策できる楽しい空間です。 しかし、「バラには棘がある」という言葉の通り、インターネットの世界にも危険が潜んでいます。それはどのようなことなのでしょうか? ウェブサイトを検索するとき、そのサイトが本当に信頼できるものだと確信できますか?閲覧しているコンテンツが正規のソースから提供されていると断言できますか?実は、クローン(偽物)サイトの事例は後を絶たず、それらを通じたフィッシング詐欺やマルウェア感染の被害も多発し
-
Google検索結果を最後にクリックした日時を追跡できるChrome拡張機能「Google When」
Googleでの検索は意外と時間を取られがちで、最初の数ページに求める情報が見つからなければ、さらに時間を浪費してしまいます。別のキーワードで再検索しても、同じリンクばかりが並ぶことが多く、うっかり同じページを何度もクリックしてしまう経験はありませんか?(履歴をこまめに削除している方なら、なおさらです) そんな悩みを解決してくれるのが、Chrome拡張機能「Google When」です。 訪問済みの検索結果の横にタイムスタンプを表示 Google Whenは、過去にクリックしたことのあるGoogle検索結果の横に、日付と時刻を自動的に表示します。これにより、どのリンクがすでに訪問済みで、どのリ