MENU

AWSの請求書(PDF)から日本円(税抜)を抽出・出力するPythonスクリプトの作成

AWSの請求書管理、特に複数アカウントの請求書を扱う場合、手作業での処理は時間がかかり、ミスも発生しやすいものです。この記事では、Pythonを使ってAWSの請求書PDFから必要な情報を自動で抽出し、CSV形式で出力する方法をご紹介します。

本スクリプトの主な特徴
  • PDF形式の請求書から直接データを抽出
  • 日本円(税抜)の金額を自動計算
  • 複数PDFの一括処理が可能
  • 顧客名、請求書番号、請求日などの情報も同時に取得
  • 結果をCSV形式で出力(Excel等での後続の処理が容易)
目次

開発環境の準備

Pythonのインストール

  1. Python公式サイト (https://www.python.org/downloads/) にアクセス
  2. 最新版のPythonをダウンロード
  3. インストーラーを実行
    • 重要:「Add Python to PATH」にチェックを入れる
  4. インストールの確認python --version

推奨エディタ:VSCode

必要なライブラリのインストール

コマンドプロンプトで以下のコマンドを実行:

pip install pdfplumber

完成版スクリプト

import pdfplumber
import re
import os
from datetime import datetime
import tkinter as tk
from tkinter import filedialog, messagebox
import csv

def extract_jpy_amount(text):
    """テキストから税抜きJPY金額を抽出する関数"""
    pattern = r"Net Charges \(After Credits/Discounts, excl\. Tax\).*?JPY\s+([0-9,]+)"
    match = re.search(pattern, text)
    return int(match.group(1).replace(',', '')) if match else None

def extract_customer_name(filename):
    """ファイル名から顧客名を抽出する関数"""
    match = re.search(r'【(.+?)】', filename)
    return match.group(1) if match else "Unknown"

def process_pdf_invoice(pdf_path):
    """PDFファイルから請求情報を抽出する関数"""
    try:
        with pdfplumber.open(pdf_path) as pdf:
            text = ''
            for page in pdf.pages:
                text += page.extract_text()

        invoice_number = re.search(r"Tax Invoice Number: ([\w-]+)", text)
        invoice_number = invoice_number.group(1) if invoice_number else "Unknown"

        invoice_date = re.search(r"Tax Invoice Date: ([^\n]+)", text)
        invoice_date = invoice_date.group(1) if invoice_date else "Unknown"

        amount = extract_jpy_amount(text)
        customer_name = extract_customer_name(os.path.basename(pdf_path))

        return {
            'customer_name': customer_name,
            'invoice_number': invoice_number,
            'invoice_date': invoice_date,
            'amount': amount,
            'filename': os.path.basename(pdf_path)
        }
    except Exception as e:
        return {'error': str(e)}

def select_file_or_folder():
    """ファイルまたはフォルダを選択するダイアログを表示"""
    root = tk.Tk()
    root.withdraw()

    print("\n処理方法を選択してください:")
    print("1: 単一のPDFファイルを処理")
    print("2: フォルダ内のすべてのPDFを処理")
    choice = input("選択 (1 or 2): ")

    if choice == "1":
        file_path = filedialog.askopenfilename(
            title="AWS請求書PDFを選択",
            filetypes=[("PDF files", "*.pdf")]
        )
        return [file_path] if file_path else []
    else:
        folder_path = filedialog.askdirectory(
            title="PDFファイルが含まれるフォルダを選択"
        )
        if folder_path:
            return [os.path.join(folder_path, f) for f in os.listdir(folder_path) 
                   if f.endswith('.pdf')]
        return []

def main():
    """メイン処理"""
    print("AWS請求書PDF解析ツール")
    print("-" * 50)

    if not os.path.exists('results'):
        os.makedirs('results')

    pdf_files = select_file_or_folder()

    if not pdf_files:
        print("PDFファイルが選択されていません。")
        return

    print(f"\n{len(pdf_files)}個のPDFファイルを処理します。")

    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    text_result_file = f'results/aws_invoice_summary_{timestamp}.txt'
    csv_result_file = f'results/aws_invoice_summary_{timestamp}.csv'

    results = []

    for pdf_file in pdf_files:
        print(f"\n処理中: {os.path.basename(pdf_file)}")
        result = process_pdf_invoice(pdf_file)
        results.append(result)

    # CSV出力
    with open(csv_result_file, 'w', encoding='utf-8-sig', newline='') as f:
        writer = csv.writer(f)
        writer.writerow(['顧客名', '請求書番号', '請求日', '税抜き金額', 'ファイル名'])
        for result in results:
            if 'error' not in result:
                writer.writerow([
                    result['customer_name'],
                    result['invoice_number'],
                    result['invoice_date'],
                    result['amount'],
                    result['filename']
                ])

    # テキスト出力
    with open(text_result_file, 'w', encoding='utf-8') as f:
        f.write("AWS請求書解析結果\n")
        f.write("-" * 50 + "\n")
        
        for result in results:
            if 'error' in result:
                f.write(f"\nファイル: {os.path.basename(pdf_file)}: "
                       f"エラー - {result['error']}\n")
            else:
                output = (
                    f"\n請求書: {result['filename']}\n"
                    f"顧客名: {result['customer_name']}\n"
                    f"請求書番号: {result['invoice_number']}\n"
                    f"請求日: {result['invoice_date']}\n"
                    f"税抜き金額: ¥{result['amount']:,}\n"
                )
                print(output)
                f.write(output)

    print(f"\n処理が完了しました。")
    print(f"テキスト形式の結果: {os.path.abspath(text_result_file)}")
    print(f"CSV形式の結果: {os.path.abspath(csv_result_file)}")

if __name__ == "__main__":
    main()
    print("\nEnterキーを押して終了してください...")
    input()

フォルダ構成

C:\Users[ユーザー名]\Desktop\aws_invoice\ # メインフォルダ

├── aws_pdf_parser.py # メインスクリプト

├── input/ # 入力PDFファイル用フォルダ(オプション)
│ ├── 【顧客A】_Invoice_JPIN24_xxxx.pdf
│ ├── 【顧客B】_Invoice_JPIN24_yyyy.pdf
│ └── 【顧客C】_Invoice_JPIN24_zzzz.pdf

├── results/ # 出力ファイル用フォルダ(自動作成)
│ ├── aws_invoice_summary_20240423_121530.csv # CSV形式の結果
│ └── aws_invoice_summary_20240423_121530.txt # テキスト形式の結果

└── requirements.txt # 必要なPythonライブラリの一覧

フォルダとファイルの説明

  1. メインフォルダ (aws_invoice)
    • デスクトップ上に作成
    • スクリプトの実行環境の基点
  2. メインスクリプト (aws_pdf_parser.py)
    • PDF解析と結果出力を行うPythonスクリプト
    • フォルダのルートに配置
  3. 入力フォルダ (input/)
    • AWS請求書のPDFファイルを配置
    • フォルダの使用は任意(GUIで別の場所も選択可能)
  4. 出力フォルダ (results/)
    • スクリプト実行時に自動作成
    • CSV形式とテキスト形式の結果ファイルが保存
    • ファイル名には実行時のタイムスタンプが付与

スクリプトの解説

主な機能

  1. PDFファイルからのテキスト抽出
  2. 請求情報の取得
    • 顧客名(ファイル名から抽出)
    • 請求書番号
    • 請求日
    • 税抜き金額
  3. CSV形式での出力

コードの重要部分の解説

PDFからのテキスト抽出

def process_pdf_invoice(pdf_path):
    with pdfplumber.open(pdf_path) as pdf:
        text = ''
        for page in pdf.pages:
            text += page.extract_text()




金額の抽出

def extract_jpy_amount(text):
    pattern = r"Net Charges \(After Credits/Discounts, excl\. Tax\).*?JPY\s+([0-9,]+)"
    match = re.search(pattern, text)
    return int(match.group(1).replace(',', '')) if match else None




顧客名の抽出

def extract_customer_name(filename):
match = re.search(r'【(.+?)】', filename)
return match.group(1) if match else "Unknown"

使用方法

  1. スクリプトの実行 aws_pdf_parser.py
  2. 処理方法の選択
    • 単一のPDFファイル処理
    • フォルダ内の全PDFファイル処理
  3. 出力ファイル
    • テキスト形式(詳細な情報)
    • CSV形式(一覧表示)

カスタマイズのポイント

抽出項目の追加

  • 為替レート
  • サービス別の利用額
  • アカウントID

出力形式の変更

  • Excel形式への出力
  • 日付形式のカスタマイズ
  • 金額のフォーマット調整

自動化の設定

  • Windowsタスクスケジューラーでの定期実行
  • 特定フォルダの監視による自動処理

注意点

  • 社内のセキュリティポリシーに従ってご利用ください
  • PDFの形式が変更された場合、抽出パターンの調整が必要になる可能性があります
  • 処理前にバックアップを取ることをお勧めします

参考リンク

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

コメント

コメントする

CAPTCHA


目次