
10,434 文字

はい、今日はですね、大規模なインターネットデータのスクレイピングのベストプラクティスについてお話させていただきます。人間みたいにブラウザを操作できる自律型のウェブスクレイパーを作って、Upworkのタスクを自動的にこなす方法なんかも紹介させていただきますわ。
ウェブスクレイピングの業界いうのは、特に2024年になってAIの影響をモロに受けとるんですわ。これまでは、アグリゲーターやEコマースなんかのネットビジネスは、競争力のある価格やオファーを維持するために、インターネットからデータをスクレイピングするだけでも、えらい数のエンジニアリソースを使うてきたんです。
普通やったら、ウェブブラウザをまねて、URLにHTTPリクエストを送って、HTMLを取得して、それから特定のDOM要素から欲しい情報を取り出すためのパース関数を書くんですけど、これがウェブサイトごとに構造が違うもんですから、サイトごとにカスタムビルドせなアカンのです。しかも、サイトの構造が変わったら、前のスクリプトは大体動かんようになってまうんですわ。
そやから、これらの会社は色んなスクレイピングシステムの開発と保守に莫大なエンジニアリソースを使うてきたわけです。でも、大手ネット企業だけやなくて、Upworkみたいなフリーランスのサイトを見てみると、毎時間たくさんのウェブスクレイパーの求人が出てるんです。
企業が特定のスクレイパーを作ってほしいいう案件で、リード獲得やリサーチ、競合価格の監視・分析、市場調査、求人情報の収集など、使用目的も様々なんです。中小企業向けの長期的なニーズがめっちゃあるんですけど、これまではコスト効率のええソリューションがなかなか見つからんかったんです。
でも、最新の大規模言語モデルと自律型システムの開発で、こういうウェブスクレイパーの開発コストが劇的に下がってきてます。実際、従来の時間とコストのほんの一部で、Upworkのほとんどのタスクをこなせる自律型スクレイパーが作れるようになってきたんです。
今日は、いくつかの例を使って、こういったタスクをどないして完了させるか見ていきましょか。単純な公開サイトから、複雑なウェブ操作が必要なスクレイピングワークフローまで、3つのカテゴリーに分けて説明させていただきます。
まず、公開されてて単純なウェブサイトについて話しましょか。これは認証やペイウォールで制限されてへんサイト、例えばWikipediaページや企業のB2Bウェブサイトみたいなもんです。こういうサイトは構造が動的すぎて、従来はスクレイピングがめっちゃ難しかったんです。サイトごとにカスタムビルドが必要やったんですわ。
ここで大規模言語モデルが革新的な変化をもたらしたんです。2つの重要な機能を導入しました。1つ目は、整理されてへん雑然としたデータから構造化された情報を抽出する能力です。生のHTMLを大規模言語モデルに投げ込むだけで、それを解析して有用な情報を抽出できるんです。OpenAIの構造化アウトプット機能を使うと、このデータ抽出がめっちゃ信頼性高くなりました。取得したいデータ構造を明確に定義すると、必ずその構造に従うてくれるんです。
もう1つは、データ抽出以外にも、エージェントの推論能力を使って、より高度なスクレイピング動作を作れることです。例えば、B2B企業の調査をする時なんかは、要件やフローが少しあいまいなことがあります。会社のウェブサイトはあるけど、欲しいデータがどのページにあるんか分からへん場合なんかです。
でも、大規模言語モデルのエージェント的な振る舞いを使うと、ウェブサイトを与えられたら、複数のページを渡り歩いて欲しい情報を見つけ出し、最終的にすべての情報を集約できるウェブスクレイパーエージェントが作れるんです。
この大規模言語モデルベースのスクレイパーエージェントはめっちゃパワフルなんですけど、これでウェブスクレイピングの問題が全部解決されたわけやないんです。よくあるのが、情報を取得するために複雑なウェブ操作が必要なサイトです。
例えば、ニュースサイトの多くは、コンテンツを取得するのにサブスクリプションやログインが必要です。それに、コンテンツの取得を邪魔するポップアップもあるし、CAPTCHAみたいな様々なアンチボット機能もあります。中には、必要なデータを集めるのに複数の操作が必要なケースもあります。
こういうサイトの場合、データを取得するために人間の操作を本当にシミュレートする必要があるんです。これが2番目のユースケースで、ちょっと複雑やけど、データを取得するプロセスはかなり具体的で反復的なものになります。実際、Upworkで見かける案件の70~80%がこのタイプのユースケースです。後でその例も見せさせていただきます。
最後に、ウェブ操作のシミュレーションだけやなく、複雑な推論タスクも必要なユースケースがあります。例えば、「今後2ヶ月でメルボルンまでの最安フライトを探して」とか、「特定の予算と期間内でコンサートチケットを買って」みたいな、もっとあいまいなリクエストです。
このタイプのユースケースは、もっと高度なエージェントの推論能力が必要で、私の経験では実験的な部分が多いんですけど、このフロンティア的なユースケースに取り組んでるプラットフォームもあるんです。
それでは、各カテゴリーのウェブスクレイピングの実装方法のベストプラクティスを見ていきましょか。まず、公開されてて単純なウェブサイトのスクレイピングについてです。
先ほど言うたように、OpenAIの構造化アウトプット機能を使えば、生のウェブサイトのHTMLから構造化された情報を抽出できます。それに、複数のページを渡り歩いて必要な情報を取得できるエージェントシステムも作れます。
2024年以前は、ほとんどの人が生のHTMLを大規模言語モデルに投げ込んでました。それでも動くことは動くんですけど、生のHTMLにはノイズが多いんで、結果が不正確になることがあるし、トークンをたくさん消費するんで、コストもかかってました。
でも今年は、大規模言語モデル用に最適化されたウェブコンテンツを提供する様々なサービスが出てきてます。このカテゴリーはFireCRから始まったんです。ウェブサイトのURLを渡すと、生のHTMLの代わりに、人間が読みやすいマークダウンファイルに変換してくれます。これなら大規模言語モデルやエージェントも処理しやすいんです。
今では、このサービスを提供する複数のプレイヤーがいます。FireCRの他に、JinaAIもあって、これも似たようなことをするReader APIを提供してます。面白いのは、使用量が少なければ基本的に無料で使えることです。認証すら必要ないAPIがあって、どのウェブサイトでも「https」の後に「r.j」を付けるだけで、自動的にマークダウン形式に変換してくれるんです。
API keyすら要らんって、めっちゃすごいですよね。誰が支払ってるんかは分かりませんけど、使用量が多くならん限り課金されへんのです。
それから、SpiderCloudというプラットフォームもあります。FireCRとJinaを本番環境で使うてた時に、使用量が急増すると、JinaとFireCRがエラーを出して、ウェブサイトのコンテンツを返せんようになることがあったんです。でも、SpiderCloudは1分間に5万ページものスクレイピングをサポートしてて、これはめっちゃすごい制限値です。
それぞれのサービスから返されるコンテンツは全部マークダウンなんですけど、微妙な違いがあります。例えば、私の近所のレストランをスクレイピングしてみたら、結果が少し違うてました。FireCRは116行のマークダウンファイル、Jinaは59行、SpiderCloudは68行を返しました。
私の観察では、FireCRはウェブサイトからできるだけ多くの情報を取得しようとします。一方、JinaのAPIはメインのテキストコンテンツに本当に焦点を当てます。SpiderCloudはその中間で、リンクも取得しようとするし、人間が読みやすいマークダウン形式に変換してくれます。
一般的に、返されるコンテンツにもいくつか違いがあるんで、ユースケースに応じて最適なものを選べます。最後にコストの話もありますね。100ページのスクレイピングにかかるコストは、Jinaは基本的に無料、SpiderCloudは100ページあたり約3セント、FireCRは最高ティアで100ページあたり約6セントです。
以前作ったエージェントスクレイパーの例を見てみましょか。FireCRを使ってウェブサイトからマークダウンデータを取得し、GPTモデルを使って必要な特定の情報を抽出します。複数のページを渡り歩いて、ウェブサイト全体から完全なメニュー項目をJSONデータとして左側に取得できます。
このタイプのエージェントには、もっと最適化できる機能があります。例えば、エージェントのメモリをどう保存するか最適化して、より大量のデータをスクレイピングできるようにしたり、既にスクレイピングしたURLを覚えておいて、同じアクションを繰り返さんようにしたりできます。
また、Llama PDFパーサーやExa検索みたいな新しいデータソースとも統合できます。興味があれば、私のコミュニティに参加してください。ウェブスクレイピングとリサーチ用のすぐ使えるエージェントテンプレートがあって、詳細なコードの解説もついてます。下のリンクをクリックしてコミュニティに参加して、エージェントテンプレートを入手してください。
これが最初のタイプ、つまり公開されてて単純なウェブサイトで、簡単にエージェントを作ってコンテンツをスクレイピングできるものです。
次は、そんなに単純やないウェブサイトで、複雑なウェブ操作が必要なものです。コンテンツをブロックするポップアップがあったり、ログイン認証が必要やったり、全てのコンテンツを取得するためにページネーションを操作せなアカンかもしれません。
こういうウェブサイトに対処するには、ウェブブラウザでの人間の操作をまねる必要があります。こういうウェブサイトの操作をシミュレートするには、一般的にSelenium、Puppeteer、Playwrightみたいなパッケージを使います。これらのパッケージは元々ウェブアプリのQAテスト用に設計されたんですけど、今ではこういうエージェントスクレイパーにも使えます。
でも、ウェブブラウザの操作をシミュレートできる自律型スクレイパーを作る時の難しい部分は、操作すべき正しいUI要素をどう見つけるかです。例えば、ウェブエージェントに検索ボックスに場所を入力させたい場合、どの入力欄が検索ボックスなのか、ウェブブラウザとエージェントが効果的にコミュニケーションを取れる方法が必要です。
LinkedInのログインページみたいに、もっと複雑なウェブサイトもあります。ここには3つの異なるサインインボタンがあるんです。単に大規模言語モデルにウェブページ全体を渡して、操作すべき正しいUI要素を抽出しろって言うても、うまくいかんことが多いんです。ここで、AgentQLっていうパッケージがめっちゃ便利なんです。正しいUI要素を特定するための基本的なビルディングモデルと、欲しい情報を含むDOMを見つける機能があって、PlaywrightにWebの操作指示を出せるんです。
これを使うと、色んな種類のウェブ自動化ができます。ポップアップウィンドウやクッキーダイアログを閉じたり、認証が必要なウェブサイトにログインしたり。SDKを使って、自然言語で取得したいUI要素を指定するだけでええんです。
AgentQLを使ってウェブスクレイピングを完全に活用する方法を示すために、Upworkの求人の中から実際の例を見てみましょか。3週間前に出てた求人で、IDEALISTっていう非営利団体やボランティア向けの求人サイトのスクレイパーを作るっていう案件です。
毎週掲載される全ての求人情報を取得して、組織名、職種、給与などの大きなリストを作り、クライアントが給与設定を適切にできるように、役職タイプや場所で簡単にソートできるようにしたいんです。
IDEALISTのサイトを見てみると、実際にログインが必要です。さっとアカウントを作ってログインしますけど、「私はロボットではありません」チェックボックスみたいなアンチボット機能もあるんで、それも対処する方法を見せますわ。
ログインした後は、ページネーションのある求人リストが出てきます。AgentQLを使って求人の詳細データを抽出して、異なるページネーション間を移動する方法を学んでいきましょう。
まず、AgentQLでアカウントを作って、Chromeプラグインをダウンロードして、どう動くか見てみましょう。プラグインをインストールしたら、スクレイピングしたいウェブサイトに行って、右クリックでインスペクションを開きます。
すると、AgentQLっていう新しいタブができてるはずです。AgentQLのウェブサイトで取得したAPIキーをここに入れる必要があります。これで実験を始められます。
取得したい項目のクエリを渡すだけでええんです。例えば、求人の総数を取得したい場合は、「number of job post total」って入れて、データをフェッチします。すると、ここにある通り3,258っていう数字が返ってきます。
配列も定義できます。この場合、「job posts」を定義して、配列記号をつけます。各求人情報の中で、組織名、職種、場所、給与、契約タイプ、リモートタイプを知りたいんです。自己説明的でない項目については、さらに説明を追加することもできます。
例えば、契約タイプについては、「フルタイム、契約社員、パートタイム」って定義できます。データをフェッチすると、その特定のページにある全ての求人情報が、会社名、職種、場所、給与、契約タイプ、リモートタイプと一緒に抽出されるのが分かります。
このプラグインを使うと、どんなクエリが実際に動いて欲しい結果を返すのかをデバッグしてテストできるんです。
一方で、ログインフローのUI要素を見つけられるかどうかもテストしたいです。今回は「login form email input」と「continue button」を試してみましょう。AgentQLにログインフォームの中からcontinueボタンを見つけてもらうために、構造を提供するのが有効です。
ウェブ要素をフェッチしてみましょう。ほら、メール入力欄とcontinueボタンの2つのUI要素が正しく返ってきました。これはめっちゃ promising ですね。
じゃあ、Pythonに移って、ウェブサイトにログインする自動化を作っていきましょう。GitHubリポジトリを開始して、VSCodeでフォルダを開きます。まず、AgentQLをインストールしましょう。
新しい仮想環境をセットアップします。VSCodeなんで、Command + Kを押して新しいPython環境をセットアップすると、自動的にコマンドラインを生成してくれます。
新しい環境に入ったら、まずAgentQLをインストールしてプロジェクトを初期化します。それから、.envファイルを作って、AgentQLのAPIキーと、IDEALISTのログイン用のメールアドレスとパスワードを入れます。
その後、scraper.pyを作って、使う予定のライブラリをいくつかインポートして、さっき入れた環境変数をロードします。
まず、メール入力欄を見つけてメールアドレスを入力し、「私はロボットではありません」チェックボックスをクリックして、continueをクリックするスクリプトを作りたいんです。
最初に初期URLとメール入力欄のクエリを定義します。これには、メール入力欄とcontinueボタンを持つログインフォームが必要です。「私はロボットではありません」チェックボックスは最初は画面に表示されてへんので、含めてません。
それで、verify_queryっていう別のクエリを作って、このverify人間チェックボックスを取得する必要があります。
じゃあ試してみましょう。まずPlaywrightでウェブセッションを開始して、AgentCで新しいページを開始します。page.go_toでURLに移動して、メール入力フォームのクエリを試します。
それから、メールアドレスをメール入力欄に入れて、verify人間UI要素が表示されるまで1000ミリ秒待ちます。その特定の要素をクエリして、AIに「私はロボットではありません」チェックボックスをクリックさせて、動くかどうか確認します。最後にcontinueボタンをクリックしてログインします。
保存して、ターミナルを開いてpython scraper.pyを実行してみましょう。あ、python-dotenvをインストールする必要がありますね。Command + Kを開いて、エラーメッセージ「no module named dotenv」を入れて送信します。
じゃあ、もう一度実行してみましょう。おっと、Playwrightをインストールする必要がありますね。playwright installを実行します。Playwrightは、ウェブブラウザセッションをシミュレートするために使うライブラリです。
インストールが完了したんで、もう一度実行してみましょう。新しいブラウザが開いて、メール入力欄を見つけてメールアドレスを入力し、「私はロボットではありません」チェックボックスが表示されたらチェックボックスを選択してログインボタンをクリックするのが分かります。
次にパスワード入力欄が表示されました。うまく動いてますね。「私はロボットではありません」チェックボックスをクリックできるのは、ちょっと面白いですね。ウェブサイトを作る時は、これをボット対策の仕組みとして頼りにせんほうがええですわ。
このログイン機能の最後のクエリとして、パスワード入力欄を追加します。パスワード入力欄をクエリして、パスワードを入力し、1秒待ってcontinueボタンをクリックします。最後にログインが完了するのを待ちます。
また、browser.contextsのストレージ状態をファイルとして保存して、後で読み込めるようにします。そうすれば、このログインプロセスを何度も繰り返す必要がなくなります。デモ用に最後に待機時間を入れて、結果が見えるようにしておきます。
もう一度試してみましょう。メールアドレスを入力して、「私はロボットではありません」ボタンをクリックして、パスワードを入力してログインをクリックします。よし、プラットフォームに正常にログインできました。
idelist_login.jsonっていうファイルができてるのが分かります。これにログイン状態が保存されてるんで、後で読み込めます。
これ全体をlogin関数でラップして、job postsをスクレイピングするためのメイン関数で新しいセッションを開始します。ファイルが存在しない場合はこのログイン関数を呼び出し、存在する場合は直接ファイルを読み込むようにします。そうすれば、毎回ログインする必要がなくなります。
状態を読み込んで、ここで定義した求人掲載ページのURLに移動します。それでほぼ完成です。さっき定義した関数を呼び出します。
次は、複数のページネーションにまたがる求人掲載コンテンツを全て取得するためのスクリプトを作れます。Chromeの拡張機能でテストした求人掲載クエリと、次のページボタンを取得するためのページネーションクエリを2つ新しく作ります。
まず、statusをtrueに設定して、次のページボタンをクリックする前の現在のURLを取得します。AgentQLから求人掲載データを取得して、その後ページネーションを取得して次のページボタンをクリックします。
完了を待った後、URLが実際に変わったかどうかをチェックします。URLが変わったということは、まだ最後のページに到達してへんっていうことなんで、全てのページをスクレイプするまで続けます。
これでほぼ完成です。ターミナルを開いてpython scraper.pyを実行してみましょう。求人掲載データについては、最後にAirtableかGoogleシートに保存したいんで、.envファイルにAirtableの新しい認証情報を追加します。APIキー、ベースID、テーブル名です。
Airtable APIに詳しくない人のために説明すると、Airtableのベースを作って、URLのこの部分がベースIDで、Star Wars TBLの後ろの部分がテーブルIDです。この2つをコピーして、ビルダーハブに行って新しいトークンを作成し、名前を付けて、スコープを追加します。
ワークスペース全体への読み書きアクセスが必要なんで、APIキーをコピーしてここに入れます。それから、pyairtableっていう新しいパッケージをインポートします。インストールしてない場合は、ターミナルを開いてpip installを実行してください。
認証情報を読み込んで、JSONのリストを受け取ってこのAirtableにデータを保存するpush_data_to_airtableっていう関数を作ります。それからメイン関数に行って、このpush_to_airtable関数を呼び出します。
これでほぼ完成です。IDEALISTを開くとスクレイピングが始まるはずです。ちょっとAirtableを開いて、並べて見てみましょう。
おお、いいですね。右側で情報が自動的に追加されてるのが分かります。給与が空のものもありますけど、実際に給与データがない求人があるみたいですね。そやから空なんでしょう。
1ページ完了したら次のページに移動して、全てのページが終わるまで新しいデータを追加し続けます。これはめっちゃすごい自動化ですよね。色んな部分に触れるんで、実際にはかなり難しいんです。
一番ええのは、ここで作ったスクリプトが他の求人掲載サイトにも自動的に適用できることです。プロセスとワークフローは、ログインしてページネーションを処理して求人掲載データを全部スクレイプするっていう感じで、かなり似てるからです。
あとは、1時間ごとか1日ごとにジョブをスケジュールして、Airtableのデータを更新し続けるようにできます。
これは一つの例ですけど、異なるEコマースサイトから価格データを収集して比較したりなど、色んなウェブ自動化ができることが想像できますよね。
これが2番目のカテゴリー、つまり複雑やけど予測可能な既知のプロセスを持つウェブサイトです。先ほど言うたように、このカテゴリーは、人々が投稿してる求人やリクエストの60~80%を占めてます。
でも、最後のカテゴリーは、ユーザーのリクエストがちょっとあいまいで、明確なステップバイステップのワークフローがないシナリオです。例えば、特定の期間中の最安フライトを見つけたい場合なんかです。
このタイプのワークフローはもっと複雑で、次に何をすべきかを決めるための推論と計画能力が必要です。私の経験では、このタイプのワークフローはめっちゃ難しいんですけど、こういうフロンティア的なワークフローを探求してる企業もあります。
多分一番ええのはMulti-oneでしょう。ウェブブラウザを自律的に操作するようなウェブエージェントの構築に焦点を当ててます。例えば、実際にチケットを予約してって頼むことができて、ワークフロー全体を完了できます。
このURLをコピーして、「このチケットを予約してください」って言うてみましょう。自動的にビューと日付を選んで次のボタンをクリックし、チケット選択ページに行って、チケットを選んで追加するのが分かります。一番下まで移動して、次のボタンを探そうとしてますけど、なんか詰まってますね。あ、でも最終的に次のボタンを見つけてクリックして、このページに移動しました。
このタイプの完全自律型ウェブエージェントは、まだめっちゃ使えるようになるまでには長い道のりがありますけど、このウェブフォームの色んな障害を乗り越えられるのは、実際にかなり印象的です。彼らはAPIも提供してますので、それも使えます。
まだ多くの人が気づいてへん機会がたくさんあります。これが2024年にエージェントと大規模言語モデルを使ってウェブスクレイピングを行うための私のベストプラクティスです。ぜひ試してみることをお勧めします。
それと、このトピックについてもっと深く掘り下げたい場合や、具体的な質問がある場合は、私のコミュニティに参加してください。これらの異なるタイプのウェブスクレイパーエージェントの詳細なステップバイステップのコード解説と、コピーペーストですぐ使えるテンプレートがあります。
もっと重要なのは、あなたが今直面してる問題を既に経験したかもしれない他のトップAIビルダーのコミュニティに参加できることです。質問を投稿して助けを得たり、私が行ってる面白いAI実験の投稿を続けたりできます。
アップデートを受け取りたい場合は、いいねと登録をお願いします。ご視聴ありがとうございました。また次回お会いしましょう。
コメント