Pythonで求人サイトのスクレイピングを自動化した話
はじめに
求人サイトの情報を定期的にチェックして、条件に合う求人をリストアップする——この作業を手動で行うと、想像以上に手間がかかります。
複数の求人サイトを巡回し、条件に合う案件を見つけ、スプレッドシートにまとめる。この繰り返し作業をPythonによるスクレイピングで自動化した事例をご紹介します。
お客様からいただいた課題
課題1:複数サイトの巡回に時間がかかる
求人情報は複数のサイトに分散しており、それぞれのサイトを手動で巡回する必要がありました。サイトごとに検索条件を設定し直す作業も含めると、情報収集だけで大きな工数を取られていました。
課題2:新着求人の見逃し
手動チェックのタイミングによっては、掲載期間が短い求人を見逃してしまうリスクがありました。特に人気の案件は早い者勝ちになることもあり、タイムリーな情報取得が重要でした。
課題3:データの一元管理ができていない
サイトごとに異なるフォーマットで求人情報が掲載されているため、一覧で比較することが困難でした。ブラウザのタブを行き来しながら比較するのは非効率的でした。
なぜPythonを選んだのか
今回はUiPath(RPA)ではなく、Pythonを選択しました。その判断理由を整理します。
Python を選んだ理由
| 観点 | 判断 |
|---|---|
| 大量データの処理 | 数千件の求人データを効率的に処理するには、プログラミング言語の方が適している |
| データ加工の柔軟性 | 重複排除、条件フィルタリング、データ正規化など、複雑なデータ加工が必要 |
| 実行環境 | サーバー上でcronにより定期実行する想定。GUIが不要 |
| 運用者 | エンジニアが運用するため、コードベースでも問題ない |
RPAかPythonかは、どちらが優れているかではなく、運用体制と要件に合った方を選ぶことが重要です。
解決策:Pythonスクレイピングシステムの開発
使用した主なライブラリ
# HTTPリクエスト
import requests
# HTML解析
from bs4 import BeautifulSoup
# データ処理
import pandas as pd
# スケジュール実行
import schedule
# ログ出力
import logging
システムの処理フロー
定期実行(cron / schedule)
↓
対象サイトへHTTPリクエスト
↓
HTMLをパースしてデータ抽出
↓
データの正規化・クリーニング
↓
前回データとの差分抽出(新着判定)
↓
CSVへ出力 / 通知送信
実装のポイント
1. リクエスト間隔の制御
対象サイトに過度な負荷をかけないよう、リクエスト間に適切な待機時間を設けました。
import time
import random
def polite_request(url):
"""サイトに配慮したリクエスト"""
time.sleep(random.uniform(1.0, 3.0)) # 1〜3秒のランダム待機
headers = {"User-Agent": "MyJobScraper/1.0"}
response = requests.get(url, headers=headers)
return response
2. 堅牢なHTML解析
求人サイトのHTML構造は変わることがあるため、要素が見つからなかった場合にもエラーで止まらない設計にしました。
def safe_extract(element, selector, default=""):
"""要素が見つからない場合はデフォルト値を返す"""
found = element.select_one(selector)
return found.get_text(strip=True) if found else default
3. 差分検出による新着通知
前回の取得結果と比較し、新しく追加された求人だけを抽出する機能を実装しました。これにより、毎回全件を確認する必要がなくなります。
def detect_new_jobs(current_jobs, previous_jobs):
"""新着求人を検出"""
previous_ids = set(previous_jobs["job_id"])
new_jobs = current_jobs[~current_jobs["job_id"].isin(previous_ids)]
return new_jobs
4. データの正規化
サイトごとに異なる表記を統一フォーマットに変換しました。
- 給与表記の統一(「月給25万円」「250,000円/月」→ 統一フォーマット)
- 勤務地の正規化(「東京都港区」「港区」→ 統一表記)
- 日付フォーマットの統一
エラーハンドリング
def scrape_with_retry(url, max_retries=3):
"""リトライ付きスクレイピング"""
for attempt in range(max_retries):
try:
response = polite_request(url)
response.raise_for_status()
return response
except requests.RequestException as e:
logging.warning(f"Attempt {attempt + 1} failed: {e}")
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # 指数バックオフ
logging.error(f"All retries failed for {url}")
return None
改善結果
1. 情報収集の自動化
複数サイトの巡回が完全に自動化され、手動での情報収集作業がゼロになりました。毎日決まった時間に最新の求人情報が収集されます。
2. 新着求人の即時把握
差分検出機能により、新しく掲載された求人をすぐに把握できるようになりました。掲載期間が短い案件の見逃しリスクが大幅に減少しています。
3. データの一元管理
異なるサイトの求人情報が統一フォーマットのCSVに集約されるため、一覧での比較が容易になりました。条件によるソートやフィルタリングもExcelで簡単に行えます。
Pythonスクレイピングの注意点
robots.txt の確認
スクレイピング前に対象サイトの
robots.txtを確認し、クロールが許可されているかを確認しましょう。
利用規約の遵守
サイトの利用規約でスクレイピングが禁止されていないか、事前に確認することが必要です。
適切なアクセス頻度
サーバーへの負荷を考慮し、リクエスト間隔を十分に空けることが大切です。短時間に大量のリクエストを送ると、IPブロックの対象になる場合があります。
まとめ
求人サイトからの情報収集を、Pythonスクレイピングで自動化しました。
改善前:
- 複数サイトの手動巡回で時間がかかる
- 新着求人の見逃しリスク
- データの一元管理ができない
改善後:
- 情報収集の完全自動化
- 差分検出による新着の即時把握
- 統一フォーマットでのデータ一元管理
Python × スクレイピングは、定期的なデータ収集業務の自動化に最適な組み合わせです。特にデータ量が多く、加工や分析が必要な場面では大きな威力を発揮します。
関連リンク: