すべての記事

50回保存の壁を回避して求人サイトをスクレイピングする

2026年、求人サイトのスクレイピングはオープンウェブ上で最も困難な作業の一つとなった。何が変化したのか、そしてタレントインテリジェンスチームがいかにしてデータ収集を継続しているのかを解説する。

課題

2026年6月のApplyArcによるベンチマークでは、5つのLinkedIn求人スクレイパーを使用して200件の実際の求人取得をテストした。3つは、約50回の保存後にアカウントがフラグ付けされたか、密かにスロットリングされた。問題なく生き残ったのは2つだけだった。

このベンチマークがすべてを物語っている。以前は求人サイトは簡単なターゲットだった。現在では、オープンウェブ上で最も困難なターゲットの一つとなっている。

求人リストのデータに依存するシステム(要員計画、給与ベンチマーク、タレントマッピング、株式調査のためのシグナルとしての採用など)を構築している場合、収集レイヤーは2年前には存在しなかった防御スタックと戦うことになる。Indeedは、見慣れないセッションに対してCAPTCHAを提示する。LinkedInは、IPローテーション全体でブラウザ側のシグナルを相関させる。Glassdoorは、IPごとではなくASNごとにrate limitを適用する。ZipRecruiterは、給与帯と掲載日をJavaScriptに押し込み、headerがスクリプトではなく人間のように見える場合にのみレンダリングする。

したがって、50回保存の壁はLinkedInの問題ではない。これはカテゴリ全体の特性である。

なぜ求人サイトは難化し続けるのか

2026年に3つの変化があり、それらが積み重なった。

1つ目は、ボット検知が振る舞いベースになったことである。かつては、静的なチェック(User-Agent、IPレピュテーション、秒間リクエスト数)で趣味レベルのスクレイパーを阻止するのに十分だった。今はそうではない。今日の防御は、サイト内をどう移動するかを監視する。どのページをどの順序でロードするか、どれだけの時間を費やすか、実際のブラウザならキャッシュするはずの同じJSバンドルを再取得するかどうかなどである。この変化についてはボット検知は振る舞いベースに移行したで書いた。求人サイトの訪問者は少数の反復可能なアクション(検索、クリック、閲覧、保存)を行うため、スクリプトがシーケンスの半分をスキップすると簡単に発見できる。そのため、求人サイトはこれを早期に採用した。

2つ目は、proxyのプールサイズが意味を持たなくなったことである。防御が接続レイヤーでのフィンガープリント相関とASNレピュテーションである場合、5000万IPの住宅用プールは役に立たない。これについてはなぜProxyプールサイズは意味を持たなくなったのかで取り上げた。有効なのは、他の誰よりも多くの出口を持つことではなく、ターゲットサイトに適切な出口を選択することである。

3つ目は法的問題である。IndeedとLinkedInの両方に、訴訟を起こす法務チームがある。収集したデータを販売しようとする者にとって、自宅のIPからパブリックスクレイパーを実行する時代は終わった。

現在のデータ収集の仕組み

2026年のタレントインテリジェンス業務において機能し続けるパターンは、分割スタックである。保護された掲示板向けの実際のブラウザによるレンダリング取得と、他のすべてのボットと同じプロバイダーからのアクセスにならないための慎重な出口選択を組み合わせる。

FourAのようなプラットフォームを使用する場合、それは2つの製品が相互に通信することを意味する。

Browserはレンダリング側を処理する。unblocker: trueを使用してURLを送信し、実際のブラウザセッションからレンダリングされたHTML、cookie、スクリーンショットを取得する。JSが評価され、遅延ロードされたフィールドが入力され、requestは最も基本的なクライアントを捕捉する接続レイヤーのチェックを通過する。proxyの選択は背後で実行される。プラットフォームはrequestごとに一意の出口を選択し、その不透明なbase36 IDをresponseで返す(Single/Browserではトップレベルのr.proxy、Autoではr.session.proxy)。これにより、後続の呼び出しでセッションの継続性が必要な場合に、同じ出口を再利用できる。ほとんどの求人サイトの作業において、Autoが適切なエントリーポイントである。各ターゲットの要件に基づいてSingle、Proxy、Browserをオーケストレーションするため、コードでそれを処理する必要はない。

import requests

r = requests.post(
    "https://api.foura.ai/api/auto",
    headers={"Authorization": "Bearer pk_live_..."},
    json={
        "url": "https://www.example-jobs.com/search?q=data+engineer&l=Remote",
        "validate": {
            "status": {"accept": [200]},
            "data":   {"accept": ["data-testid=\"job-card\""],
                       "fail":   ["Just a moment", "captcha"]},
        },
    },
).json()

# r["data"] or r["body"]   — rendered content (Auto picks Single→"data" or Browser→"body" per host)
# r["session"]              — { "proxy": "<base36 id>", "cookies": [...], "userAgent": "..." }
# Reuse r["session"]["proxy"] on the next call to stick to the same exit, or pass it
# via `ignoreProxies: [<id>]` to force a different one.

これが実際に何をもたらすかについて、2つ留意点がある。

ApplyArcスタイルの50回保存の壁は、主にセッションの問題であり、プールの問題ではない。慎重にローテーションされた実際のブラウザセッションは、生のHTTPクライアントよりもはるかに長く、rate limitに引っかかることなく持続する。また、responseには生の出口ではなく不透明なproxy IDが含まれるため、コードはシンプルに保たれ、どの出口がどのrequestを処理したかを追跡する必要はない。

2つ目の留意点は、スニペットに含まれていないことについてである。サイト間の重複排除(LinkedIn、Indeed、および企業独自の採用ページにある同じデータエンジニアの役割で、わずかに異なる3つの役職名)は、ユーザー自身の問題であり、収集レイヤーの問題ではない。私たちは、チームがこれを過小評価しているのを見てきた。正規化はフェッチよりも多くのエンジニアリング時間を消費し、ほとんどのタレントインテリジェンス製品が最終的に競合する領域である。

結果

3つの求人サイトで200社を追跡するタレントインテリジェンスチームは、週に約50,000回のページフェッチを必要とする。検索結果、求人の詳細ページ、および時折行われる企業ページの更新である。そのワークロードで達成したい数値は次の通りである。

  • Indeedクラスのターゲットでの95%を超える成功率。成功とは、給与帯と掲載日が入力された状態でレンダリングされたHTMLを取得することを意味する。
  • レンダリングと出口の選択を含め、エンドツーエンドで1件あたり0.004ドル未満のコスト
  • アクティブな求人に対する6から12時間間隔の更新。これにより、採用シグナルダッシュボードが市場から遅れることはない。

これらの数値は、この分割スタックパターンを実行しているチームの報告に基づく例示である。実際のコストは、どのサイトをターゲットにするか、および新しい投稿をどれだけ積極的にフィルタリングするかによって異なる。

重要なポイント

現在、求人サイトは一般的なEコマースよりも、アドテクやチケット販売に近い難易度になっている。これは決定的な変化であり、2024年に機能していたスクレイピングライブラリが、2026年に同じ壁に引っかかり続ける理由を説明している。

それを乗り越えてスケールするチームは、「スクレイパー」を作業単位として考えるのをやめる。彼らはセッション、出口、重複排除を3つの別個の懸念事項として捉え、エンジニアが週の時間を3つ目に費やせるように、最初の2つのインフラストラクチャを購入する。最も安価な求人データとは、フラグ付けされた後に再収集する必要がなかったデータのことである。