Python サーバーレス Scraper 入門 – 24時間自動収集を実現する最新テクニック

当サイトはアフィリエイトを含むプロモーションを掲載しています

目次

はじめに:なぜ今、サーバーレススクレイピングが注目されているのか

「毎日同じWebサイトから情報を手動で収集している」「定期的な価格チェックを自動化したい」「でもサーバーの管理は面倒…」

こんな悩みを抱えているエンジニアの方は多いのではないでしょうか。

従来のWebスクレイピングでは、24時間稼働させるためにVPSやEC2インスタンスを常時起動させる必要がありました。しかし、サーバーレス技術の登場により、サーバー管理不要で、使った分だけの課金で済む新しいスクレイピング手法が実現可能になりました。

本記事では、Python初心者でも実装できるサーバーレススクレイピングの構築方法を、実践的なサンプルコードとともに解説します。

サーバーレススクレイピングの3つのメリット

1. コスト削減効果が絶大

従来のVPSを使った場合、月額数千円〜1万円程度のコストがかかりますが、サーバーレスなら月額数百円以下で運用可能です。

運用方法月額コストメンテナンス
VPS/EC23,000円〜10,000円必要(OS更新等)
サーバーレス0円〜500円ほぼ不要

2. スケーラビリティの自動化

アクセス数が増えても自動的にスケールするため、サーバーがダウンする心配がありません。

3. セキュリティ対策の簡素化

OSやミドルウェアのセキュリティパッチ適用が不要で、セキュリティリスクを大幅に削減できます。

主要3サービスの特徴と選び方

AWS Lambda

  • メリット:最も成熟したサービス、豊富な連携サービス
  • デメリット:初期設定が複雑、15分の実行時間制限
  • こんな人におすすめ:AWSの他サービスと連携したい方

Google Cloud Functions

  • メリット:シンプルな設定、Googleサービスとの親和性
  • デメリット:日本語ドキュメントが少ない
  • こんな人におすすめ:初めてサーバーレスに挑戦する方

Azure Functions

  • メリット:タイマートリガーが標準装備、Visual Studioとの連携
  • デメリット:他2つに比べて情報が少ない
  • こんな人におすすめ:定期実行メインで使いたい方

編集部のおすすめ:初心者の方には、設定がシンプルなGoogle Cloud Functionsから始めることを推奨します。慣れてきたら、より高度な機能を持つAWS Lambdaへの移行を検討しましょう。

実践:Google Cloud Functionsで作る価格監視Bot

ここからは、実際にECサイトの価格を定期的に監視するBotを作ってみましょう。

前提条件

  • Googleアカウント
  • Python 3.7以上の基礎知識
  • クレジットカード(無料枠内で利用可能)

Step1: プロジェクトの作成

まず、Google Cloud Consoleでプロジェクトを作成します。

# Google Cloud SDKのインストール(未インストールの場合)
curl https://sdk.cloud.google.com | bash

# プロジェクトの作成
gcloud projects create price-monitor-bot --name="価格監視Bot"
gcloud config set project price-monitor-bot

Step2: スクレイピング関数の実装

main.pyを作成し、以下のコードを記述します。

import requests
from bs4 import BeautifulSoup
import json
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
from google.cloud import firestore

def price_monitor(request):
    """
    商品の価格を監視し、変動があればメール通知する関数
    """
    # 監視対象のURL(例:架空のECサイト)
    target_url = "https://example-shop.com/product/12345"
    
    try:
        # Webページの取得
        response = requests.get(target_url, headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        })
        response.raise_for_status()
        
        # HTMLの解析
        soup = BeautifulSoup(response.text, 'html.parser')
        
        # 価格要素の取得(サイトに応じて調整が必要)
        price_element = soup.find('span', class_='price')
        if not price_element:
            return {'error': '価格要素が見つかりません'}, 404
        
        # 価格を数値に変換
        current_price = int(price_element.text.replace('¥', '').replace(',', ''))
        
        # Firestoreから前回の価格を取得
        db = firestore.Client()
        doc_ref = db.collection('prices').document('product_12345')
        doc = doc_ref.get()
        
        if doc.exists:
            previous_price = doc.to_dict().get('price', 0)
            
            # 価格が変動した場合
            if current_price != previous_price:
                # 価格変動を通知
                send_notification(current_price, previous_price)
        
        # 現在の価格を保存
        doc_ref.set({
            'price': current_price,
            'updated_at': datetime.now(),
            'url': target_url
        })
        
        return {
            'status': 'success',
            'price': current_price,
            'timestamp': datetime.now().isoformat()
        }, 200
        
    except requests.RequestException as e:
        return {'error': f'リクエストエラー: {str(e)}'}, 500
    except Exception as e:
        return {'error': f'予期しないエラー: {str(e)}'}, 500

def send_notification(current_price, previous_price):
    """価格変動をメールで通知"""
    # 実際の実装では環境変数から取得
    sender_email = "[email protected]"
    receiver_email = "[email protected]"
    
    # 価格変動の計算
    price_diff = current_price - previous_price
    percent_change = (price_diff / previous_price) * 100
    
    # メール本文の作成
    subject = f"【価格変動通知】商品価格が{'上昇' if price_diff > 0 else '下落'}しました"
    body = f"""
    監視中の商品で価格変動を検知しました。
    
    前回価格: ¥{previous_price:,}
    現在価格: ¥{current_price:,}
    変動額: ¥{price_diff:,} ({percent_change:+.1f}%)
    
    チェック時刻: {datetime.now().strftime('%Y年%m月%d日 %H:%M')}
    """
    
    # ここでメール送信処理を実装
    print(f"通知: {subject}")
    print(body)

Step3: 必要なライブラリの定義

requirements.txtを作成します。

requests==2.28.2
beautifulsoup4==4.11.2
google-cloud-firestore==2.11.0

Step4: デプロイと定期実行の設定

# Cloud Functionsへのデプロイ
gcloud functions deploy price_monitor \
    --runtime python39 \
    --trigger-http \
    --allow-unauthenticated \
    --region asia-northeast1 \
    --memory 512MB

# Cloud Schedulerで1時間ごとに実行
gcloud scheduler jobs create http price-monitor-job \
    --schedule="0 * * * *" \
    --uri="https://asia-northeast1-price-monitor-bot.cloudfunctions.net/price_monitor" \
    --http-method=GET \
    --location=asia-northeast1

高度なテクニック:動的サイトへの対応

JavaScriptで動的に生成されるサイトの場合、Seleniumを使用する必要があります。ただし、サーバーレス環境での実装には工夫が必要です。

ヘッドレスChromeの設定例

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def create_driver():
    """サーバーレス環境用のChromeドライバーを作成"""
    options = Options()
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--disable-extensions')
    options.add_argument('--single-process')
    
    # メモリ使用量を削減
    options.add_argument('--disable-images')
    options.add_argument('--disable-javascript')  # 必要に応じて
    
    # Cloud Functions環境では事前に配置したバイナリを使用
    options.binary_location = '/opt/headless-chromium'
    
    driver = webdriver.Chrome(
        executable_path='/opt/chromedriver',
        chrome_options=options
    )
    
    return driver

実装時の注意点とトラブルシューティング

1. メモリ不足エラーの対処法

スクレイピング処理は意外とメモリを消費します。特にSeleniumを使用する場合は、最低512MB以上のメモリを割り当てましょう。

2. タイムアウトエラーの回避

サーバーレス関数には実行時間の制限があります:

  • AWS Lambda: 15分
  • Google Cloud Functions: 9分
  • Azure Functions: 無制限(Premium プラン)

長時間の処理が必要な場合は、処理を分割するか、別のアーキテクチャを検討しましょう。

3. レート制限への対応

import time
import random

def polite_scraping(urls):
    """礼儀正しいスクレイピング"""
    results = []
    for url in urls:
        # ランダムな待機時間(1〜3秒)
        time.sleep(random.uniform(1, 3))
        
        # スクレイピング処理
        result = scrape_page(url)
        results.append(result)
    
    return results

編集部が実際に使ってみた結果

弊社編集部では、実際にGoogle Cloud Functionsを使って競合他社の求人情報を毎日収集するシステムを構築しました。

結果

  • 月額コスト:約200円(1日1回実行)
  • 開発期間:2日間
  • 収集成功率:98%以上

特に印象的だったのは、サーバー管理の手間が一切なくなったことです。一度デプロイすれば、あとは自動で動き続けてくれます。

セキュリティとコンプライアンス

サーバーレススクレイピングを実装する際は、以下の点に注意しましょう:

  1. robots.txtの確認:対象サイトのスクレイピングポリシーを必ず確認
  2. 個人情報の取り扱い:収集したデータの保管・利用には十分注意
  3. アクセス頻度の調整:サーバーに負荷をかけないよう配慮

コスト最適化のテクニック

無料枠を最大限活用する方法

サービス無料枠月間実行回数の目安
AWS Lambda100万リクエスト/月1分ごと実行でも余裕
Google Cloud Functions200万リクエスト/月30秒ごとでも可能
Azure Functions100万リクエスト/月1分ごと実行でOK

メモリ使用量の最適化

# 不要なライブラリのインポートを避ける
# ✗ 悪い例
import pandas as pd  # 重いライブラリ

# ✓ 良い例
import csv  # 軽量な標準ライブラリ

まとめ:次のステップへ

サーバーレススクレイピングは、従来の方法に比べて圧倒的にコストパフォーマンスが高く、運用も簡単です。本記事で紹介した基本的な実装から始めて、徐々に高度な機能を追加していくことをおすすめします。

スキルアップのロードマップ

  1. 初級:静的サイトの定期スクレイピング(本記事の内容)
  2. 中級:動的サイトへの対応、データ分析との連携
  3. 上級:機械学習との組み合わせ、異常検知システムの構築

著者プロフィール LIFキャリア編集部。実際にサーバーレス技術を活用したシステム開発経験を持つエンジニアチームが、実践的な情報をお届けします。

参考資料

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次