← ブログ一覧に戻る
業務自動化

Pythonで求人サイトのスクレイピングを自動化した話

#Python#スクレイピング#データ収集#自動化#BeautifulSoup

はじめに

求人サイトの情報を定期的にチェックして、条件に合う求人をリストアップする——この作業を手動で行うと、想像以上に手間がかかります。

複数の求人サイトを巡回し、条件に合う案件を見つけ、スプレッドシートにまとめる。この繰り返し作業を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 × スクレイピングは、定期的なデータ収集業務の自動化に最適な組み合わせです。特にデータ量が多く、加工や分析が必要な場面では大きな威力を発揮します。


関連リンク: