Skip to content

求人クローラー

概要

各エントリー媒体(ATS: Applicant Tracking System)から求人情報を自動取得し、BUSON のデータベースに保存するスクリプト群です。

項目内容
対応媒体数13 媒体(求人クローラー 12 + 求職者クローラー 1)
実行方法cd backend && npm run crawl:<媒体名>
自動化技術Playwright(Chromium ヘッドレス)/ HTTP fetch
出力先jobs テーブル(求人)/ hr_candidates テーブル(求職者)

共通 CLI オプション

全クローラーで以下のオプションが利用可能です。

bash
cd backend && npm run crawl:<媒体> -- [オプション]
オプション説明
--dry-runDB に書き込まず、取得結果をログ出力のみ
--limit N処理対象の企業数を N 件に制限
--company "名前"指定企業名(部分一致)のみ処理(複数企業対応クローラーのみ)
--verbose詳細ログを出力
--inspectスクリーンショットと HTML を tmp/<名前>-inspect/ に保存
--helpヘルプを表示

クローラー一覧

一覧表

npm スクリプトATS 媒体対象企業取得方式認証方式複数企業
crawl:herpHERP17 社(ハードコード)HTTP fetch不要(公開 URL)Yes
crawl:jobcanジョブカン採用管理動的取得(ドロップダウン)PlaywrightEmail / PasswordYes
crawl:talentioTalentio動的取得(React props)PlaywrightEmail / PasswordYes
crawl:freeeWantedly Agent動的取得(企業一覧)PlaywrightCookie or Email / PWYes
crawl:kanrikun採用一括かんりくん動的取得(テーブル)PlaywrightUsername / PasswordYes
crawl:persona-sunterrasPERSONA動的取得(サイドバー)PlaywrightEmail / PasswordYes
crawl:axol-akkodisaxol(マイナビ)AKKODISPlaywrightUsername / PasswordNo
crawl:axol-avantaxol(マイナビ)AVANTPlaywrightUsername / PasswordNo
crawl:axol-daiwaaxol(マイナビ)大和総研PlaywrightUsername / PasswordNo
crawl:jpostingjpostingデロイトPlaywrightBasic 認証 + フォームNo
crawl:greenhouse-paypaycardGreenhousePayPay カードPlaywrightEmail / Password(2段階)No
crawl:hitolink-careritzHITO-LinkケアリッツPlaywrightOIDC 2段階No
crawl:agreAGRE ARMS設定値で指定PlaywrightCookie or LoginNo

AGRE ARMS について

crawl:agre は唯一、求人ではなく**求職者(応募者)**を取り込むクローラーです。出力先は hr_candidates テーブルです。

各クローラーの詳細

HERP

唯一ブラウザ自動化を使わない HTTP fetch ベースのクローラーです。HERP は HTML 内に window.herpCb(null, {...}) として JSON データを埋め込んでいるため、DOM レンダリングなしでデータ取得が可能です。

項目内容
URLhttps://agent.herp.cloud/p/{token}
認証不要(公開エージェント URL)。一部企業は HTTP Basic 認証
対象企業17 社(types.ts にハードコード)

対象企業一覧: JDSC, Finatext, 情報戦略テクノロジー, リンクアンドモチベーション, LITALICO, ソニーペイメントサービス, AGEST, HEROZ, オープンロジ, メディアドゥ, TYL, GMO サイバーセキュリティ, エアークローゼット, サイバーセキュリティクラウド, エスキュービズム, Work X, スマートドライブ

取得フロー:

  1. 一覧ページの HTML から window.herpCb() の JSON を正規表現で抽出
  2. ListRequisitions レスポンスから求人一覧を取得
  3. 各求人の詳細ページで ShowRequisition レスポンスを取得
  4. 公開フィールド + エージェント専用フィールドを Markdown に構成

環境変数:

変数名必須説明
HERP_BASIC_AUTH_CSCNoサイバーセキュリティクラウド用 Basic 認証(user:password
HERP_ENTRY_PLATFORM_IDNoentry_platforms.id
bash
# 全社取得
npm run crawl:herp

# 特定企業のみ
npm run crawl:herp -- --company "JDSC"

# ドライラン(DB書き込みなし)
npm run crawl:herp -- --dry-run --verbose

ジョブカン採用管理(Jobcan)

ジョブカンのエージェントポータルから求人を取得します。ログイン後、ドロップダウンから企業を動的に切り替えながらクロールします。

項目内容
URLhttps://ats.jobcan.jp
認証Email / Password フォームログイン
企業切替#change_agent_client ドロップダウンから AJAX 切替

取得フロー:

  1. ログイン → ドロップダウンから企業一覧を取得
  2. 企業ごとに AJAX で切替(/_/agents/change_client?client_id={id}
  3. 求人テーブルの各行をクリック → 詳細ページを取得
  4. ページネーション対応(aria-label="Next"

環境変数:

変数名必須説明
JOBCAN_LOGIN_EMAILYesログインメール
JOBCAN_LOGIN_PASSWORDYesログインパスワード
JOBCAN_ENTRY_PLATFORM_IDNoentry_platforms.id
bash
npm run crawl:jobcan
npm run crawl:jobcan -- --company "INTLOOP" --verbose

Talentio

Talentio のエージェントポータルから求人を取得します。React テーブルの data-react-props 属性から企業一覧を抽出します。

項目内容
URLhttps://agent.talentio.com
認証Email / Password フォームログイン
企業取得React の data-react-props 属性から抽出

取得フロー:

  1. ログイン → 求人一覧ページへ遷移
  2. data-react-props から企業リストを抽出
  3. テーブルの各行をクリック → 詳細ページ → goBack() で一覧に戻る
  4. ページネーション対応

環境変数:

変数名必須説明
TALENTIO_LOGIN_EMAILYesログインメール
TALENTIO_LOGIN_PASSWORDYesログインパスワード
bash
npm run crawl:talentio
npm run crawl:talentio -- --company "SmartHR" --limit 3

Wantedly Agent(freee)

Wantedly Agent(旧 freee 採用管理)のエージェントポータルから求人を取得します。MUI コンポーネントベースの SPA です。

項目内容
URLhttps://hire.wantedly.com/agent
認証Cookie モード(優先)または Email / Password
企業取得/agent/companies の MUI テーブルから動的取得

取得フロー:

  1. ログイン → 企業一覧ページで MUI テーブルの読み込みを待機
  2. 企業 ID を <img> タグの URL パスから抽出
  3. 各企業の求人一覧 → 行クリック → 「詳細を見る」ボタン → モーダルから説明文取得
  4. MUI ページネーション対応

Cookie モードについて

reCAPTCHA やレート制限でログインが失敗する場合、ブラウザの DevTools → Network → Cookie ヘッダーの値を FREEE_LOGIN_COOKIE に設定することで回避できます。

環境変数:

変数名必須説明
FREEE_LOGIN_COOKIENoCookie 文字列(優先使用)
FREEE_LOGIN_EMAILNoログインメール(Cookie 未使用時)
FREEE_LOGIN_PASSWORDNoログインパスワード
FREEE_ENTRY_PLATFORM_IDNoentry_platforms.id
bash
npm run crawl:freee
npm run crawl:freee -- --company "企業名" --dry-run

採用一括かんりくん(Kanrikun)

career-cloud.asia のエージェントポータルから求人を取得します。全企業の求人が単一の一覧テーブルに混在して表示されます。

項目内容
URLhttps://www.career-cloud.asia
認証Username / Password フォームログイン
企業取得テーブルの企業名カラムから取得

取得フロー:

  1. ログイン → /agent/mypage/jobs へ遷移
  2. テーブルから求人サマリーを収集(企業名はカラムとして含まれる)
  3. 各求人の詳細ページを訪問して説明文を取得
  4. ページネーション対応(「次へ」リンク)

環境変数:

変数名必須説明
KANRIKUN_LOGIN_USERNAMEYesログインユーザー名
KANRIKUN_LOGIN_PASSWORDYesログインパスワード
KANRIKUN_ENTRY_PLATFORM_IDNoentry_platforms.id
bash
npm run crawl:kanrikun
npm run crawl:kanrikun -- --company "企業名" --verbose

PERSONA(Sun Terras)

PERSONA(Assign 社)のエージェントポータルから求人を取得します。Quasar/Vue.js ベースの SPA で、全てのナビゲーションが URL 変化なしで行われる点が特徴です。

項目内容
URLhttps://www.agent.persona-ats.com/
認証Email / Password(AWS Amplify Authenticator)
企業取得左サイドバーから動的取得

取得フロー:

  1. ログイン(Amplify Authenticator の「サインイン」ボタン)
  2. 左サイドバーから企業一覧を取得
  3. 企業クリック → サブメニュー展開 → 各求人をクリック → メインエリアから詳細取得
  4. 企業処理後はベース URL に戻って状態をリセット

URL が変わらない SPA

PERSONA は完全な SPA のため、各求人に固有の URL がありません。求人の重複判定は entry_url ではなくタイトル一致upsertByTitle)で行います。

環境変数:

変数名必須説明
PERSONA_SUNTERRAS_EMAILYesログインメール
PERSONA_SUNTERRAS_PASSWORDYesログインパスワード
PERSONA_SUNTERRAS_BASE_URLNoベース URL(デフォルト: 上記)
PERSONA_SUNTERRAS_ENTRY_PLATFORM_IDNoentry_platforms.id
bash
npm run crawl:persona-sunterras
npm run crawl:persona-sunterras -- --company "Sun terras"

axol 系(AKKODIS / AVANT / 大和総研)

マイナビが提供する axol エージェントポータルのクローラーです。テナントごとに個別のクローラーがあります。3 つとも同様のアーキテクチャで、一覧ページに全求人の詳細がインライン展開されているため、詳細ページへの遷移が不要です。

テナントnpm スクリプトベース URL
AKKODIScrawl:axol-akkodishttps://w2.axol.jp/mjn/c/3565jrg
AVANTcrawl:axol-avanthttps://w2.axol.jp/mqd/c/523pfw7
大和総研crawl:axol-daiwahttps://w2.axol.jp/mpm/c/7zi45qh

取得フロー:

  1. ログイン(Username / Password)
  2. 一覧ページからインライン展開された求人情報を一括取得
  3. エントリー URL は job_encid(暗号化 ID)から動的に構築
  4. ページネーション対応(10 件/ページ、「次へ>>」リンク)

環境変数:

変数名対象必須
AXOL_AKKODIS_USERNAMEAKKODISYes
AXOL_AKKODIS_PASSWORDAKKODISYes
AXOL_LOGIN_USERNAMEAVANTYes
AXOL_LOGIN_PASSWORDAVANTYes
AXOL_DAIWA_USERNAME大和総研Yes
AXOL_DAIWA_PASSWORD大和総研Yes
AXOL_DAIWA_BASE_URL大和総研No
AXOL_DAIWA_COMPANY_NAME大和総研No
AXOL_ENTRY_PLATFORM_IDAKKODIS / AVANTNo
AXOL_DAIWA_ENTRY_PLATFORM_ID大和総研No
bash
npm run crawl:axol-akkodis -- --dry-run
npm run crawl:axol-avant -- --verbose
npm run crawl:axol-daiwa -- --inspect

jposting(デロイト)

jposting のエージェントポータルから求人を取得します。全求人が単一ページに表示されるため、ページネーションや詳細ページ遷移は不要です。

項目内容
URLhttps://pgst05.jposting.net/agent/
認証HTTP Basic 認証(必須)+ フォームログイン(任意)
パース方式正規表現ベースの HTML パーサー

取得フロー:

  1. HTTP Basic 認証でアクセス(Playwright の httpCredentials オプション)
  2. フォームログインがある場合は追加で実行
  3. ページ全体の HTML を正規表現でパース(parseAllJobs()
  4. 求人タイトルを <a href="entry.phtml?job_code=..."> から抽出
  5. フィールド行を valign="top" テーブル行から抽出

環境変数:

変数名必須説明
JPOSTING_BASIC_AUTHYesBasic 認証(user:password 形式)
JPOSTING_BASE_URLNoベース URL
JPOSTING_LOGIN_IDNoフォームログイン ID
JPOSTING_LOGIN_PASSWORDNoフォームログインパスワード
JPOSTING_COMPANY_NAMENo企業名(デフォルト: デロイト
JPOSTING_ENTRY_PLATFORM_IDNoentry_platforms.id
bash
npm run crawl:jposting -- --dry-run --verbose

Greenhouse(PayPay カード)

Greenhouse のエージェンシーポータルから求人を取得します。2 段階のログインフロー(Email → Password)が特徴です。

項目内容
URLhttps://app.greenhouse.io
認証Email / Password(2 段階ログイン)
エントリー URL全求人で共通(/agency/candidates/new

取得フロー:

  1. ログイン(Email 入力 → Next → Password 入力)
  2. Agencies テーブルから「PayPay Card」リンクをクリック
  3. 求人テーブルの各行ボタンをクリック → 詳細を取得
  4. 求人の重複判定はタイトル一致(upsertByTitle

エントリー URL が共通

Greenhouse のエージェンシーポータルでは求人ごとの個別エントリー URL がないため、全求人に同じ URL が設定されます。

環境変数:

変数名必須説明
GREENHOUSE_LOGIN_EMAILYesログインメール
GREENHOUSE_LOGIN_PASSWORDYesログインパスワード
GREENHOUSE_ENTRY_PLATFORM_IDNoentry_platforms.id
bash
npm run crawl:greenhouse-paypaycard -- --dry-run

HITO-Link リクルーティング(Persol 社)のエージェントポータルから求人を取得します。OIDC 認証による 2 段階ログインが必要です。

項目内容
URLhttps://ats-agent.hito-link.jp
認証OIDC 2 段階(OIDC ボタン → IdP ログインフォーム)
特徴SPA のため各遷移で待機が必要(1.5〜3 秒)

取得フロー:

  1. ランディングページの OIDC ボタンをクリック
  2. IdP ログインフォームで Email / Password を入力
  3. 求人一覧からサマリーを収集
  4. 各求人の詳細ページを訪問して説明文を取得
  5. ページネーション対応(最大 50 ページ)

環境変数:

変数名必須説明
HITOLINK_CARERITZ_EMAILYesログインメール
HITOLINK_CARERITZ_PASSWORDYesログインパスワード
HITOLINK_CARERITZ_LOGIN_URLNoログイン URL
HITOLINK_CARERITZ_SITE_HOME_URLNoサイトホーム URL
HITOLINK_CARERITZ_COMPANY_NAMENo企業名(デフォルト: ケアリッツ
HITOLINK_CARERITZ_ENTRY_PLATFORM_IDNoentry_platforms.id
bash
npm run crawl:hitolink-careritz -- --dry-run --verbose

AGRE ARMS(求職者取込)

AGRE ARMS から**求職者(応募者)**情報を取り込むクローラーです。他のクローラーとは異なり、求人ではなく hr_candidates テーブルにデータを保存します。

項目内容
URLAGRE_ARMS_BASE_URL で指定
認証Cookie モード(推奨)またはログインモード
出力先hr_candidates テーブル

reCAPTCHA について

ログインモードでは reCAPTCHA にブロックされる可能性があります。その場合はブラウザの DevTools から Cookie を取得して AGRE_ARMS_COOKIE に設定してください。

環境変数:

変数名必須説明
AGRE_ARMS_BASE_URLYesベース URL
AGRE_ARMS_CUSTOMER_IDYesテナント顧客 ID
AGRE_ARMS_COOKIENoCookie 文字列(推奨)
AGRE_ARMS_LOGIN_IDNoログイン ID(Cookie 未使用時)
AGRE_ARMS_PASSWORDNoログインパスワード
bash
npm run crawl:agre -- --dry-run
npm run crawl:agre:inspect  # スクリーンショット付き

データフロー

出力フィールド(共通)

各クローラーは以下のフィールドを取得して jobs テーブルに upsert します。

フィールド説明
title求人タイトル
description求人説明文(Markdown 形式)
entry_urlエントリー URL(求人応募ページ)
is_public公開求人かどうか
company_id企業 ID(companies テーブルへの FK)

重複判定

方式使用クローラー説明
upsertByEntryUrl大多数エントリー URL の一致で判定(標準)
upsertByTitleGreenhouse, PERSONA固有 URL がない媒体でタイトル一致で判定

ファイル構成

各クローラーは以下の 4 ファイルで構成されます。

backend/src/scripts/crawlers/<媒体名>/
├── index.ts           # エントリーポイント(CLI解析、環境変数読み込み、実行)
├── <Name>Crawler.ts   # クローラー本体(ログイン、ページ遷移、データ収集)
├── <Name>Parser.ts    # パーサー(HTML→構造化データの変換)
└── types.ts           # 型定義

トラブルシューティング

ログインに失敗する

  • reCAPTCHA: Cookie モードに切り替える(AGRE、Wantedly Agent)
  • 2 段階認証: セレクタ変更がないか --inspect で HTML を確認
  • セッション切れ: Cookie 文字列を再取得

求人が 0 件で終了する

  • --verbose で詳細ログを確認
  • --inspect でスクリーンショットと HTML を保存して UI 変更がないか確認
  • ATS 側で求人ページの HTML 構造が変わった可能性がある

タイムアウトエラー

  • SPA 系クローラー(HITO-Link、PERSONA)は遷移に時間がかかるため、ネットワーク環境を確認
  • --limit 1 で少数の企業のみテストする

関連ファイル

役割パス
クローラー群backend/src/scripts/crawlers/
npm スクリプト定義backend/package.json
企業リポジトリbackend/src/infrastructure/repositories/supabase/CompanyRepository.ts
求人リポジトリbackend/src/infrastructure/repositories/supabase/JobRepository.ts
環境変数テンプレートbackend/.env.example