売上予測を
見える化

  • 登録不要
  • 基本無料
  • データ安全
無料で始める

請求書も
かんたん作成

  • テンプレート
  • 自動計算
  • PDF出力
今すぐ試す

📊 売上予測を今すぐ始める

未来の売上が、今わかる。登録不要・基本無料

Monerionを無料で試す →

【業務自動化革命】Playwright+Selenium二段階アプローチ!安定ブラウザ自動操作の5つの実践技法

毎月の経費精算、定期的な競合価格調査、レポートのダウンロード...。「また同じ作業か」とため息をついている業務担当者は多いのではないでしょうか。

これらの繰り返し作業を自動化したいと思っても、従来の方法では「要素が見つからない」「UIが変わったら動かなくなった」といった問題で挫折することが少なくありません。

しかし、Playwright MCP + Claude Codeの組み合わせにより、この状況が根本的に変わりました。

従来の業務自動化が失敗する理由

よくある自動化の課題

業務でブラウザ自動操作を試みた際の典型的な問題:

  • 要素特定の困難さ: 「このボタンのCSSセレクタがわからない」
  • タイミングの問題: 「ページの読み込み完了を待てずにエラー」
  • UIの微変更: 「昨日まで動いていたのに、突然動かなくなった」
  • メンテナンス性: 「作った本人しか修正できない」

根本的な問題:探索と実装の混同

従来のアプローチでは、「どの要素をクリックすればいいか」を探す探索プロセスと、「実際に動作するスクリプト」を作る実装プロセスが混同されていました。

この結果、探索段階での試行錯誤が実装品質を下げ、メンテナンス性の低いスクリプトが量産されてしまいます。

二段階アプローチの威力

フェーズ1: Playwright MCPで探索的要素特定

目的: 安定して操作できる要素の特定

1. 実際のブラウザでページを開く
2. 複数のセレクタパターンを試行
3. 最も安定したセレクタを発見
4. 動作タイミングを確認

Playwright MCPの強み: - リアルタイム試行錯誤: ブラウザを見ながら要素を特定 - 複数セレクタの比較: CSS、XPath、テキストベース等を並行試験 - 動的待機の確認: 要素の表示タイミングを実測

フェーズ2: Claude CodeでPython + Seleniumの本番実装

目的: 堅牢で保守しやすい実行スクリプト

# 自動生成される堅牢なスクリプト例
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import logging
import time

class BusinessAutomation:
    def __init__(self):
        self.setup_logging()
        self.driver = self.setup_driver()

    def setup_logging(self):
        logging.basicConfig(level=logging.INFO)
        self.logger = logging.getLogger(__name__)

    def safe_click(self, selector, timeout=10, retry=3):
        """安全なクリック処理(リトライ付き)"""
        for attempt in range(retry):
            try:
                element = WebDriverWait(self.driver, timeout).until(
                    EC.element_to_be_clickable((By.CSS_SELECTOR, selector))
                )
                element.click()
                self.logger.info(f"Successfully clicked: {selector}")
                return True
            except Exception as e:
                self.logger.warning(f"Click attempt {attempt + 1} failed: {e}")
                time.sleep(2)
        return False

Claude Codeによる実装の強み: - エラーハンドリング: 想定される全ての例外を処理 - ログ出力: 実行状況の可視化 - リトライ機構: 一時的な問題への対応 - 設定の外部化: 環境に依存しない設計

実践例1: 経費精算の自動化

業務シナリオ

毎月20件程度の経費をWebシステムに入力する作業を自動化

フェーズ1: Playwright MCPでの探索

1. 経費精算システムにログイン
2. 新規登録ボタンの最適セレクタを特定
3. 各入力フィールドの識別方法を確認
4. 保存処理のタイミングを測定

発見事項: - 日付フィールドはカレンダー形式のため、直接入力が困難 - 金額入力後にバリデーションで3秒の待機が必要 - 添付ファイルのアップロードは非同期処理

フェーズ2: Claude Codeでの実装

def process_expenses(self, csv_file_path):
    """CSVファイルから経費データを読み込み、自動入力"""
    expenses = pd.read_csv(csv_file_path)

    for index, expense in expenses.iterrows():
        try:
            # 新規登録画面を開く
            self.safe_click("button[data-action='new-expense']")

            # 日付入力(カレンダー対応)
            self.input_date("input[name='expense-date']", expense['date'])

            # 金額入力(バリデーション待機)
            self.input_amount("input[name='amount']", expense['amount'])

            # 説明入力
            self.safe_input("textarea[name='description']", expense['description'])

            # 添付ファイル(非同期アップロード)
            if expense['receipt_path']:
                self.upload_receipt(expense['receipt_path'])

            # 保存処理
            if self.save_expense():
                self.logger.info(f"Expense {index + 1} processed successfully")
            else:
                self.logger.error(f"Failed to save expense {index + 1}")

        except Exception as e:
            self.logger.error(f"Error processing expense {index + 1}: {e}")
            self.capture_screenshot(f"error_expense_{index + 1}.png")

業務効果: - 作業時間: 2時間 → 15分 - エラー率: 5% → 0% - 担当者の負担軽減

実践例2: 競合価格の定期監視

業務シナリオ

週1回、主要競合3社のサイトから価格情報を収集

フェーズ1での重要な発見

  • サイトA: JavaScriptによる動的価格表示(3秒待機必要)
  • サイトB: ログイン必須、セッション管理が重要
  • サイトC: レート制限あり(リクエスト間隔2秒必要)

フェーズ2での実装

class CompetitorPriceMonitor:
    def __init__(self):
        self.results = []
        self.setup_driver_with_stealth()

    def monitor_all_competitors(self):
        competitors = [
            {'name': 'CompanyA', 'url': 'https://...', 'method': self.scrape_company_a},
            {'name': 'CompanyB', 'url': 'https://...', 'method': self.scrape_company_b},
            {'name': 'CompanyC', 'url': 'https://...', 'method': self.scrape_company_c},
        ]

        for competitor in competitors:
            try:
                prices = competitor['method'](competitor['url'])
                self.results.append({
                    'company': competitor['name'],
                    'prices': prices,
                    'timestamp': datetime.now()
                })
            except Exception as e:
                self.send_alert(f"Failed to scrape {competitor['name']}: {e}")

    def scrape_company_a(self, url):
        """JavaScript動的価格に対応"""
        self.driver.get(url)

        # 動的コンテンツの読み込み待機
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, "price-loaded"))
        )

        prices = []
        price_elements = self.driver.find_elements(By.CSS_SELECTOR, ".product-price")
        for element in price_elements:
            prices.append({
                'product': element.get_attribute('data-product'),
                'price': element.text
            })
        return prices

業務効果: - 調査時間: 1時間 → 5分 - データの一貫性向上 - 価格変動の早期発見

実践例3: 月次レポートの自動ダウンロード

業務シナリオ

各種管理画面から月次データを定期取得

実装のポイント

def download_monthly_reports(self, target_month):
    """月次レポートの一括ダウンロード"""
    reports = [
        {'name': 'sales', 'selector': '#sales-report-btn'},
        {'name': 'inventory', 'selector': '#inventory-report-btn'},
        {'name': 'customer', 'selector': '#customer-report-btn'},
    ]

    for report in reports:
        try:
            # 日付範囲設定
            self.set_date_range(target_month)

            # レポート生成
            self.safe_click(report['selector'])

            # 生成完了待機(進行状況バー監視)
            self.wait_for_report_generation()

            # ダウンロード実行
            download_path = self.download_report(report['name'], target_month)

            # ファイル整理
            self.organize_downloaded_file(download_path, report['name'])

        except Exception as e:
            self.logger.error(f"Failed to download {report['name']}: {e}")

導入時の重要ポイント

セキュリティ考慮事項

認証情報の管理:

import os
from cryptography.fernet import Fernet

class SecureCredentials:
    def __init__(self):
        self.cipher = Fernet(os.environ['AUTOMATION_KEY'])

    def get_credentials(self, service_name):
        encrypted_data = os.environ[f'{service_name}_CREDENTIALS']
        return self.cipher.decrypt(encrypted_data.encode()).decode()

アクセス制御: - 自動化専用アカウントの利用 - 最小権限の原則 - 実行ログの保管

エラー監視とアラート

def send_alert(self, message, severity='WARNING'):
    """業務チームへのアラート通知"""
    if severity == 'CRITICAL':
        # Slack/Teams通知
        self.send_slack_notification(message)
        # メール通知
        self.send_email_alert(message)
    else:
        # ログ記録のみ
        self.logger.warning(message)

メンテナンス性の確保

設定の外部化:

# automation_config.yaml
selectors:
  login_button: "button[data-testid='login']"
  amount_field: "input[name='amount']"
  save_button: ".save-action"

timeouts:
  page_load: 10
  element_wait: 5
  download_wait: 30

retry_counts:
  click_retry: 3
  input_retry: 2

ドキュメント化: - 各処理の業務的意味 - 設定パラメータの説明 - トラブルシューティング手順

まとめ

Playwright MCP + Claude Codeの二段階アプローチにより、業務自動化は新しいレベルに到達しました。

従来の課題: - 要素特定の困難さ - 不安定な動作 - メンテナンス性の低さ

新アプローチの効果: - 探索と実装の分離による高品質化 - エラーハンドリングとリトライによる堅牢性 - 設定外部化とドキュメント化による保守性

重要なのは、技術的な実装だけでなく、業務プロセス全体を見直す視点です。自動化により生まれた時間を、より価値の高い業務に投入することで、真の業務効率化が実現できるのです。

安定したブラウザ自動操作による業務革新は、もはや一部の技術者だけのものではありません。適切なツールと手法により、すべての業務担当者が恩恵を受けられる時代が到来しています。

🎯 今すぐ始める

Monerionで売上予測を始めましょう

登録不要ですぐ使える
データは端末に安全保存
基本機能は永久無料
無料で使ってみる

30秒で始められます

← ブログトップに戻る