Appearance
求人クローラー
概要
各エントリー媒体(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-run | DB に書き込まず、取得結果をログ出力のみ |
--limit N | 処理対象の企業数を N 件に制限 |
--company "名前" | 指定企業名(部分一致)のみ処理(複数企業対応クローラーのみ) |
--verbose | 詳細ログを出力 |
--inspect | スクリーンショットと HTML を tmp/<名前>-inspect/ に保存 |
--help | ヘルプを表示 |
クローラー一覧
一覧表
| npm スクリプト | ATS 媒体 | 対象企業 | 取得方式 | 認証方式 | 複数企業 |
|---|---|---|---|---|---|
crawl:herp | HERP | 17 社(ハードコード) | HTTP fetch | 不要(公開 URL) | Yes |
crawl:jobcan | ジョブカン採用管理 | 動的取得(ドロップダウン) | Playwright | Email / Password | Yes |
crawl:talentio | Talentio | 動的取得(React props) | Playwright | Email / Password | Yes |
crawl:freee | Wantedly Agent | 動的取得(企業一覧) | Playwright | Cookie or Email / PW | Yes |
crawl:kanrikun | 採用一括かんりくん | 動的取得(テーブル) | Playwright | Username / Password | Yes |
crawl:persona-sunterras | PERSONA | 動的取得(サイドバー) | Playwright | Email / Password | Yes |
crawl:axol-akkodis | axol(マイナビ) | AKKODIS | Playwright | Username / Password | No |
crawl:axol-avant | axol(マイナビ) | AVANT | Playwright | Username / Password | No |
crawl:axol-daiwa | axol(マイナビ) | 大和総研 | Playwright | Username / Password | No |
crawl:jposting | jposting | デロイト | Playwright | Basic 認証 + フォーム | No |
crawl:greenhouse-paypaycard | Greenhouse | PayPay カード | Playwright | Email / Password(2段階) | No |
crawl:hitolink-careritz | HITO-Link | ケアリッツ | Playwright | OIDC 2段階 | No |
crawl:agre | AGRE ARMS | 設定値で指定 | Playwright | Cookie or Login | No |
AGRE ARMS について
crawl:agre は唯一、求人ではなく**求職者(応募者)**を取り込むクローラーです。出力先は hr_candidates テーブルです。
各クローラーの詳細
HERP
唯一ブラウザ自動化を使わない HTTP fetch ベースのクローラーです。HERP は HTML 内に window.herpCb(null, {...}) として JSON データを埋め込んでいるため、DOM レンダリングなしでデータ取得が可能です。
| 項目 | 内容 |
|---|---|
| URL | https://agent.herp.cloud/p/{token} |
| 認証 | 不要(公開エージェント URL)。一部企業は HTTP Basic 認証 |
| 対象企業 | 17 社(types.ts にハードコード) |
対象企業一覧: JDSC, Finatext, 情報戦略テクノロジー, リンクアンドモチベーション, LITALICO, ソニーペイメントサービス, AGEST, HEROZ, オープンロジ, メディアドゥ, TYL, GMO サイバーセキュリティ, エアークローゼット, サイバーセキュリティクラウド, エスキュービズム, Work X, スマートドライブ
取得フロー:
- 一覧ページの HTML から
window.herpCb()の JSON を正規表現で抽出 ListRequisitionsレスポンスから求人一覧を取得- 各求人の詳細ページで
ShowRequisitionレスポンスを取得 - 公開フィールド + エージェント専用フィールドを Markdown に構成
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
HERP_BASIC_AUTH_CSC | No | サイバーセキュリティクラウド用 Basic 認証(user:password) |
HERP_ENTRY_PLATFORM_ID | No | entry_platforms.id |
bash
# 全社取得
npm run crawl:herp
# 特定企業のみ
npm run crawl:herp -- --company "JDSC"
# ドライラン(DB書き込みなし)
npm run crawl:herp -- --dry-run --verboseジョブカン採用管理(Jobcan)
ジョブカンのエージェントポータルから求人を取得します。ログイン後、ドロップダウンから企業を動的に切り替えながらクロールします。
| 項目 | 内容 |
|---|---|
| URL | https://ats.jobcan.jp |
| 認証 | Email / Password フォームログイン |
| 企業切替 | #change_agent_client ドロップダウンから AJAX 切替 |
取得フロー:
- ログイン → ドロップダウンから企業一覧を取得
- 企業ごとに AJAX で切替(
/_/agents/change_client?client_id={id}) - 求人テーブルの各行をクリック → 詳細ページを取得
- ページネーション対応(
aria-label="Next")
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
JOBCAN_LOGIN_EMAIL | Yes | ログインメール |
JOBCAN_LOGIN_PASSWORD | Yes | ログインパスワード |
JOBCAN_ENTRY_PLATFORM_ID | No | entry_platforms.id |
bash
npm run crawl:jobcan
npm run crawl:jobcan -- --company "INTLOOP" --verboseTalentio
Talentio のエージェントポータルから求人を取得します。React テーブルの data-react-props 属性から企業一覧を抽出します。
| 項目 | 内容 |
|---|---|
| URL | https://agent.talentio.com |
| 認証 | Email / Password フォームログイン |
| 企業取得 | React の data-react-props 属性から抽出 |
取得フロー:
- ログイン → 求人一覧ページへ遷移
data-react-propsから企業リストを抽出- テーブルの各行をクリック → 詳細ページ →
goBack()で一覧に戻る - ページネーション対応
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
TALENTIO_LOGIN_EMAIL | Yes | ログインメール |
TALENTIO_LOGIN_PASSWORD | Yes | ログインパスワード |
bash
npm run crawl:talentio
npm run crawl:talentio -- --company "SmartHR" --limit 3Wantedly Agent(freee)
Wantedly Agent(旧 freee 採用管理)のエージェントポータルから求人を取得します。MUI コンポーネントベースの SPA です。
| 項目 | 内容 |
|---|---|
| URL | https://hire.wantedly.com/agent |
| 認証 | Cookie モード(優先)または Email / Password |
| 企業取得 | /agent/companies の MUI テーブルから動的取得 |
取得フロー:
- ログイン → 企業一覧ページで MUI テーブルの読み込みを待機
- 企業 ID を
<img>タグの URL パスから抽出 - 各企業の求人一覧 → 行クリック → 「詳細を見る」ボタン → モーダルから説明文取得
- MUI ページネーション対応
Cookie モードについて
reCAPTCHA やレート制限でログインが失敗する場合、ブラウザの DevTools → Network → Cookie ヘッダーの値を FREEE_LOGIN_COOKIE に設定することで回避できます。
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
FREEE_LOGIN_COOKIE | No | Cookie 文字列(優先使用) |
FREEE_LOGIN_EMAIL | No | ログインメール(Cookie 未使用時) |
FREEE_LOGIN_PASSWORD | No | ログインパスワード |
FREEE_ENTRY_PLATFORM_ID | No | entry_platforms.id |
bash
npm run crawl:freee
npm run crawl:freee -- --company "企業名" --dry-run採用一括かんりくん(Kanrikun)
career-cloud.asia のエージェントポータルから求人を取得します。全企業の求人が単一の一覧テーブルに混在して表示されます。
| 項目 | 内容 |
|---|---|
| URL | https://www.career-cloud.asia |
| 認証 | Username / Password フォームログイン |
| 企業取得 | テーブルの企業名カラムから取得 |
取得フロー:
- ログイン →
/agent/mypage/jobsへ遷移 - テーブルから求人サマリーを収集(企業名はカラムとして含まれる)
- 各求人の詳細ページを訪問して説明文を取得
- ページネーション対応(「次へ」リンク)
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
KANRIKUN_LOGIN_USERNAME | Yes | ログインユーザー名 |
KANRIKUN_LOGIN_PASSWORD | Yes | ログインパスワード |
KANRIKUN_ENTRY_PLATFORM_ID | No | entry_platforms.id |
bash
npm run crawl:kanrikun
npm run crawl:kanrikun -- --company "企業名" --verbosePERSONA(Sun Terras)
PERSONA(Assign 社)のエージェントポータルから求人を取得します。Quasar/Vue.js ベースの SPA で、全てのナビゲーションが URL 変化なしで行われる点が特徴です。
| 項目 | 内容 |
|---|---|
| URL | https://www.agent.persona-ats.com/ |
| 認証 | Email / Password(AWS Amplify Authenticator) |
| 企業取得 | 左サイドバーから動的取得 |
取得フロー:
- ログイン(Amplify Authenticator の「サインイン」ボタン)
- 左サイドバーから企業一覧を取得
- 企業クリック → サブメニュー展開 → 各求人をクリック → メインエリアから詳細取得
- 企業処理後はベース URL に戻って状態をリセット
URL が変わらない SPA
PERSONA は完全な SPA のため、各求人に固有の URL がありません。求人の重複判定は entry_url ではなくタイトル一致(upsertByTitle)で行います。
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
PERSONA_SUNTERRAS_EMAIL | Yes | ログインメール |
PERSONA_SUNTERRAS_PASSWORD | Yes | ログインパスワード |
PERSONA_SUNTERRAS_BASE_URL | No | ベース URL(デフォルト: 上記) |
PERSONA_SUNTERRAS_ENTRY_PLATFORM_ID | No | entry_platforms.id |
bash
npm run crawl:persona-sunterras
npm run crawl:persona-sunterras -- --company "Sun terras"axol 系(AKKODIS / AVANT / 大和総研)
マイナビが提供する axol エージェントポータルのクローラーです。テナントごとに個別のクローラーがあります。3 つとも同様のアーキテクチャで、一覧ページに全求人の詳細がインライン展開されているため、詳細ページへの遷移が不要です。
| テナント | npm スクリプト | ベース URL |
|---|---|---|
| AKKODIS | crawl:axol-akkodis | https://w2.axol.jp/mjn/c/3565jrg |
| AVANT | crawl:axol-avant | https://w2.axol.jp/mqd/c/523pfw7 |
| 大和総研 | crawl:axol-daiwa | https://w2.axol.jp/mpm/c/7zi45qh |
取得フロー:
- ログイン(Username / Password)
- 一覧ページからインライン展開された求人情報を一括取得
- エントリー URL は
job_encid(暗号化 ID)から動的に構築 - ページネーション対応(10 件/ページ、「次へ>>」リンク)
環境変数:
| 変数名 | 対象 | 必須 |
|---|---|---|
AXOL_AKKODIS_USERNAME | AKKODIS | Yes |
AXOL_AKKODIS_PASSWORD | AKKODIS | Yes |
AXOL_LOGIN_USERNAME | AVANT | Yes |
AXOL_LOGIN_PASSWORD | AVANT | Yes |
AXOL_DAIWA_USERNAME | 大和総研 | Yes |
AXOL_DAIWA_PASSWORD | 大和総研 | Yes |
AXOL_DAIWA_BASE_URL | 大和総研 | No |
AXOL_DAIWA_COMPANY_NAME | 大和総研 | No |
AXOL_ENTRY_PLATFORM_ID | AKKODIS / AVANT | No |
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 -- --inspectjposting(デロイト)
jposting のエージェントポータルから求人を取得します。全求人が単一ページに表示されるため、ページネーションや詳細ページ遷移は不要です。
| 項目 | 内容 |
|---|---|
| URL | https://pgst05.jposting.net/agent/ |
| 認証 | HTTP Basic 認証(必須)+ フォームログイン(任意) |
| パース方式 | 正規表現ベースの HTML パーサー |
取得フロー:
- HTTP Basic 認証でアクセス(Playwright の
httpCredentialsオプション) - フォームログインがある場合は追加で実行
- ページ全体の HTML を正規表現でパース(
parseAllJobs()) - 求人タイトルを
<a href="entry.phtml?job_code=...">から抽出 - フィールド行を
valign="top"テーブル行から抽出
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
JPOSTING_BASIC_AUTH | Yes | Basic 認証(user:password 形式) |
JPOSTING_BASE_URL | No | ベース URL |
JPOSTING_LOGIN_ID | No | フォームログイン ID |
JPOSTING_LOGIN_PASSWORD | No | フォームログインパスワード |
JPOSTING_COMPANY_NAME | No | 企業名(デフォルト: デロイト) |
JPOSTING_ENTRY_PLATFORM_ID | No | entry_platforms.id |
bash
npm run crawl:jposting -- --dry-run --verboseGreenhouse(PayPay カード)
Greenhouse のエージェンシーポータルから求人を取得します。2 段階のログインフロー(Email → Password)が特徴です。
| 項目 | 内容 |
|---|---|
| URL | https://app.greenhouse.io |
| 認証 | Email / Password(2 段階ログイン) |
| エントリー URL | 全求人で共通(/agency/candidates/new) |
取得フロー:
- ログイン(Email 入力 → Next → Password 入力)
- Agencies テーブルから「PayPay Card」リンクをクリック
- 求人テーブルの各行ボタンをクリック → 詳細を取得
- 求人の重複判定はタイトル一致(
upsertByTitle)
エントリー URL が共通
Greenhouse のエージェンシーポータルでは求人ごとの個別エントリー URL がないため、全求人に同じ URL が設定されます。
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
GREENHOUSE_LOGIN_EMAIL | Yes | ログインメール |
GREENHOUSE_LOGIN_PASSWORD | Yes | ログインパスワード |
GREENHOUSE_ENTRY_PLATFORM_ID | No | entry_platforms.id |
bash
npm run crawl:greenhouse-paypaycard -- --dry-runHITO-Link(ケアリッツ)
HITO-Link リクルーティング(Persol 社)のエージェントポータルから求人を取得します。OIDC 認証による 2 段階ログインが必要です。
| 項目 | 内容 |
|---|---|
| URL | https://ats-agent.hito-link.jp |
| 認証 | OIDC 2 段階(OIDC ボタン → IdP ログインフォーム) |
| 特徴 | SPA のため各遷移で待機が必要(1.5〜3 秒) |
取得フロー:
- ランディングページの OIDC ボタンをクリック
- IdP ログインフォームで Email / Password を入力
- 求人一覧からサマリーを収集
- 各求人の詳細ページを訪問して説明文を取得
- ページネーション対応(最大 50 ページ)
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
HITOLINK_CARERITZ_EMAIL | Yes | ログインメール |
HITOLINK_CARERITZ_PASSWORD | Yes | ログインパスワード |
HITOLINK_CARERITZ_LOGIN_URL | No | ログイン URL |
HITOLINK_CARERITZ_SITE_HOME_URL | No | サイトホーム URL |
HITOLINK_CARERITZ_COMPANY_NAME | No | 企業名(デフォルト: ケアリッツ) |
HITOLINK_CARERITZ_ENTRY_PLATFORM_ID | No | entry_platforms.id |
bash
npm run crawl:hitolink-careritz -- --dry-run --verboseAGRE ARMS(求職者取込)
AGRE ARMS から**求職者(応募者)**情報を取り込むクローラーです。他のクローラーとは異なり、求人ではなく hr_candidates テーブルにデータを保存します。
| 項目 | 内容 |
|---|---|
| URL | AGRE_ARMS_BASE_URL で指定 |
| 認証 | Cookie モード(推奨)またはログインモード |
| 出力先 | hr_candidates テーブル |
reCAPTCHA について
ログインモードでは reCAPTCHA にブロックされる可能性があります。その場合はブラウザの DevTools から Cookie を取得して AGRE_ARMS_COOKIE に設定してください。
環境変数:
| 変数名 | 必須 | 説明 |
|---|---|---|
AGRE_ARMS_BASE_URL | Yes | ベース URL |
AGRE_ARMS_CUSTOMER_ID | Yes | テナント顧客 ID |
AGRE_ARMS_COOKIE | No | Cookie 文字列(推奨) |
AGRE_ARMS_LOGIN_ID | No | ログイン ID(Cookie 未使用時) |
AGRE_ARMS_PASSWORD | No | ログインパスワード |
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 の一致で判定(標準) |
upsertByTitle | Greenhouse, 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 |