• #Amazon
  • #PA-API
  • #GitHub Actions
  • #Python
  • #設計書

Amazon 価格監視ツール設計書(PA-API + GitHub Actions + CSV)

1. ゴール / 概要

  • 対象:Amazon.co.jp の特定商品
  • 手段:Amazon Product Advertising API(PA-API)を定期的に叩き、価格を取得
  • ストレージ:すべて CSV(Excel で編集可能な前提)
  • 処理フロー:
  1. プロダクト一覧 CSV から「監視対象商品(ASIN + ターゲット価格)」を読み込む
  2. 各商品の現在価格を PA-API で取得
  3. 商品ごとの履歴 CSV に追記
  4. 現在価格がターゲット価格以下になった商品について通知を送信(メール等)
  5. 一覧から商品を削除した場合、その商品は以降監視されないが、履歴 CSV は残る

2. 商品コード(ASIN)について

  • Amazon には、ASIN (Amazon Standard Identification Number) という商品IDがあり、
  • 同一マーケットプレイス(今回は Amazon.co.jp)内では、ASIN は一意(ユニーク)
  • 本システムでは、この ASIN を「商品コード」かつ主キー として扱う。
  • ユーザー操作:
  • 商品ページ URL から ASIN を抽出して「products.csv」に入力するか、
  • 生成AI側の実装で「URL → ASIN 抽出」を行っても良い(仕様としては ASIN を持っていればOK)。

3. 全体アーキテクチャ

3.1 コンポーネント構成

  • CSV ストレージ
  • data/products.csv … 監視対象の商品一覧(Excel で編集)
  • data/history/{ASIN}.csv … 各商品の価格履歴ログ
  • 価格取得スクリプト(Python)
  • src/fetch_prices.py
  • やること:products.csv を読み込み → PA-API で価格取得 → history CSV に追記 → 通知判定
  • 通知スクリプト(Python)
  • src/notify.py
  • やること:fetch_prices.py から渡された「通知対象商品一覧」を元に、メール or Webhook を送信
  • GitHub Actions
  • .github/workflows/price_watcher.yml
  • スケジュール実行(例:1日1回)+手動実行(dispatch)の両方

3.2 想定テクノロジースタック

  • 言語:Python 3.10+
  • 依存ライブラリ例:
  • requests(PA-API 呼び出し)
  • python-amazon-paapi 等の PA-API クライアント(採用は実装側判断で可)
  • pandas(CSV 操作を楽にするため、任意)
  • 通知手段:
  • まずは メール送信 を前提
* 例:SMTP(Gmail 等) or SendGrid API など
  • 実装側で抽象化しやすいよう、インターフェイスのみ仕様で定義

4. ディレクトリ構成(例)

project-root/
  README.md
  data/
    products.csv
    history/
      # 例)B0CN28DNQH.csv など ASIN ごとのファイル
  src/
    fetch_prices.py
    notify.py
    paapi_client.py   # PA-API 呼び出しラッパ
    config.py
  .github/
    workflows/
      price_watcher.yml
  requirements.txt

5. CSV 仕様(データモデル)

5.1 data/products.csv(監視対象リスト)

  • 役割:監視対象の商品と、ターゲット価格などのメタ情報を保持する。
  • フォーマット:UTF-8 / カンマ区切り
  • 1 行目はヘッダー行。

カラム定義

カラム名必須説明
asinYesstringAmazon ASIN(商品コード、ユニーク)例: B0CN28DNQH
nameYesstring商品名(任意のわかりやすい名前)
urlYesstring商品ページの URL(Amazon.co.jp)
target_priceYesnumber通知を発火させる「ターゲット価格」(税込、JPY を想定)
activeNoboolean監視対象フラグ。true または false。未指定なら true 扱い。
notesNostringメモ/備考

挙動仕様

  • ユーザーが Excel でこの CSV を編集する想定。
  • 新規商品を追跡したい場合:
  • 新しい行を追加(ASIN、name、url、target_price を入力)。
  • この時点で次回の定期実行から監視対象となる。
  • 監視をやめたい場合:
  • 行を削除する、または active=false にする。
  • 履歴 CSV (history/{ASIN}.csv) は残るが、以降更新されない。

5.2 data/history/{ASIN}.csv(商品別価格履歴)

  • 役割:各 ASIN の価格履歴を保存。
  • ファイル名:data/history/<ASIN>.csv
  • 例:data/history/B0CN28DNQH.csv
  • 1 商品につき 1 ファイル(Excel で言う「商品ごとのシート」に相当)。

カラム定義

カラム名必須説明
timestampYesstringISO8601 日時(例: 2025-12-06T00:00:00+09:00
dateYesstring日付のみ(例: 2025-12-06)。集計用に冗長保持。
asinYesstring対象商品の ASIN
priceYesnumber取得した販売価格(JPY)
currencyYesstring通貨コード。JPY 固定想定。
sourceNostring価格のソース(AmazonOffer / LowestNewPrice など)。
raw_jsonNostringPA-API のレスポンスのうち、必要な部分を JSON 文字列として保存(任意)。

追記ルール

  • fetch_prices.py 実行ごとに、商品の数 × 1 行 を追加。
  • 行追加は「末尾」へ追記。
  • ファイルが存在しない場合:
  • 新規作成し、ヘッダー行 + データ 1 行を出力。
  • ファイルが存在する場合:
  • 最終行の date が同一日でも、そのまま追記(デイリー 1 回実行想定だが、複数回でも時系列ログとして許容)。

6. 処理フロー詳細

6.1 fetch_prices.py のロジック

  1. data/products.csv を読み込み
  • active != false の行のみを対象とする。
  • 各行から asin, name, url, target_price を取り出す。
  1. 各 ASIN について PA-API を呼び出し、「現在価格」を取得
  • paapi_client.get_current_price(asin) のような抽象関数でラップする。
  • 戻り値例:
{
  "asin": "B0CN28DNQH",
  "price": 19800,
  "currency": "JPY",
  "source": "AmazonOffer"
}
```
3. 履歴 CSV (`data/history/<ASIN>.csv`) に追記
  • timestamp は現在日時(タイムゾーン +09:00)。
  • dateYYYY-MM-DD
  1. 通知判定
  • target_price が数値として有効な場合、以下を行う:
 * 最新の価格 `current_price` と比較し、
   `current_price <= target_price` のとき「通知候補」に追加。
  • 同じ条件で何度も通知しない工夫(推奨仕様):
 * 当該 ASIN の履歴ファイルを読み込み、
   * 「直前の価格 > target_price」かつ「今回の価格 <= target_price」のときだけ通知する。
   * つまり、「ターゲットを初めて割り込んだタイミング」でのみ通知。

5. 通知候補一覧を notify.py に渡す

  • 形式例(Python の dict list):
to_notify = [
  {
    "asin": "B0CN28DNQH",
    "name": "BARWING エアロバイク",
    "url": "https://www.amazon.co.jp/...",
    "target_price": 18000,
    "current_price": 17500,
    "timestamp": "2025-12-06T00:00:00+09:00"
  },
  ...
]
```

---

## 6.2 notify.py のロジック(Resend でメール送信)

### 6.2.1 前提
  • メール送信は Resend の公式 API を利用する。
  • Python からは HTTP(S) で https://api.resend.com/emails に POST する。
  • 認証は Authorization: Bearer <RESEND_API_KEY> ヘッダで行う。

6.2.2 環境変数

notify.py は以下の環境変数を参照する。

  • RESEND_API_KEY Resend のダッシュボードで発行した API キー。
  • MAIL_FROM 送信元メールアドレス(例:"alerts@example.com")。 Resend 側で認証済みのドメイン/アドレスを利用すること。
  • MAIL_TO 送信先メールアドレス。カンマ区切りで複数指定可(例:"user1@example.com,user2@example.com")。

6.2.3 入力(to_notify)

fetch_prices.py から以下形式のリストを受け取る:

to_notify = [
  {
    "asin": "B0CN28DNQH",
    "name": "BARWING エアロバイク",
    "url": "https://www.amazon.co.jp/...",
    "target_price": 18000,
    "current_price": 17500,
    "timestamp": "2025-12-06T00:00:00+09:00"
  },
  # ...
]

6.2.4 処理フロー

  1. to_notify が空 (len == 0) の場合は何もせず終了。
  2. MAIL_FROM, MAIL_TO, RESEND_API_KEY がすべて設定されているか検証。足りなければログ出力して終了(エラー終了でもよい)。
  3. MAIL_TO をカンマ区切りで分割し、受信者リストを作成。

6.2.5 Resend へのリクエスト仕様

  • エンドポイント: POST https://api.resend.com/emails
  • ヘッダ:
  • Authorization: Bearer <RESEND_API_KEY>
  • Content-Type: application/json
  • ボディ例(単純なテキストメール):
{
  "from": "Your Name <alerts@example.com>",
  "to": ["user1@example.com", "user2@example.com"],
  "subject": "Amazon価格アラート: 3件の商品がターゲット価格を下回りました",
  "text": "本文(プレーンテキスト)"
}

6.2.6 メール本文のフォーマット(text)

本文はプレーンテキストでよい。例:

以下の商品がターゲット価格を下回りました。

1) BARWING エアロバイク
   ASIN: B0CN28DNQH
   現在価格: 17,500 円
   ターゲット価格: 18,000 円
   時刻: 2025-12-06T00:00:00+09:00
   URL: https://www.amazon.co.jp/...

2) ...

生成ルール:

  • 先頭に簡単な説明文。
  • 各商品を番号付きで列挙。
  • 含める項目:
  • name
  • asin
  • current_price
  • target_price
  • timestamp
  • url

6.2.7 エラーハンドリング

  • Resend API が 2xx 以外を返した場合:
  • ステータスコードとレスポンスボディをログ出力。
  • 必要に応じて例外を投げて GitHub Actions を failed にしてもよい(運用ポリシー次第)。
  • ネットワークエラーなど:
  • リトライはとりあえずなし(シンプルに失敗としてログ出力)。
  • 将来的に tenacity 等のリトライライブラリで拡張可能な構成にしておく。

7. 環境変数 / シークレット定義(Resend 版)

GitHub Secrets(あるいは Actions Variables)に少なくとも以下を設定する:

7.1 Resend 関連

  • RESEND_API_KEY Resend の API キー。

7.2 メール送信設定

  • MAIL_FROM Resend で利用可能な送信元アドレス(例: alerts@yourdomain.com)。
  • MAIL_TO 通知を受け取りたい自分のメールアドレス(複数可)。

7.3 PA-API 関連(前仕様と同じ)

  • AMAZON_PAAPI_ACCESS_KEY
  • AMAZON_PAAPI_SECRET_KEY
  • AMAZON_PAAPI_ASSOCIATE_TAG
  • AMAZON_PAAPI_REGION

8. GitHub Actions 側での設定補足

.github/workflows/price_watcher.yml 内で、env または with 経由で Python に渡す想定:

env:
  RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
  MAIL_FROM: ${{ secrets.MAIL_FROM }}
  MAIL_TO: ${{ secrets.MAIL_TO }}
  AMAZON_PAAPI_ACCESS_KEY: ${{ secrets.AMAZON_PAAPI_ACCESS_KEY }}
  AMAZON_PAAPI_SECRET_KEY: ${{ secrets.AMAZON_PAAPI_SECRET_KEY }}
  AMAZON_PAAPI_ASSOCIATE_TAG: ${{ secrets.AMAZON_PAAPI_ASSOCIATE_TAG }}
  AMAZON_PAAPI_REGION: "us-east-1"  # 例

あとは実装側で:

  • fetch_prices.py → 通知対象を notify.py に渡す
  • notify.py → 上記 Resend API 仕様でメール送信

という流れにすれば、Resend 前提の構成になります。


9. エラーハンドリング / 考慮事項

  • PA-API のレスポンスがエラーの場合:
  • 該当 ASIN についてはログにエラーを残し、他の商品処理は続行。
  • 失敗した商品についてはその回の履歴追記・通知は行わない。
  • レートリミット:
  • 商品数が増えた場合にレートリミットにかからないよう、ASIN 数 × 実行頻度を調整する。
  • CSV の競合:
  • 本システムでは、GitHub Actions 実行ごとに commit/push は行わない前提でもよいが、
  • 履歴を GitHub 上に残したい場合は、最後に git commit && git push するワークフローも別途検討可能(ただしコンフリクト対策が必要)。
  • 通貨・税:
  • 本仕様では Amazon.co.jp / JPY / 税込を前提とし、PA-API から取得する価格をそのまま price として保存する。

10. 拡張案(将来的なオプション)

  • Slack / Discord / LINE Notify など、メール以外の通知チャネル追加
  • products.csv に以下の項目を追加して柔軟性アップ
  • upper_limit_price(高すぎる場合のアラート)
  • category(家電、トレーニング用品など)
  • last_notified_at(通知制御を CSV 側で行う)
  • 価格だけでなく、在庫状況・ポイント付与率なども取得して履歴に保存(PA-API で取得できる範囲に依存)

以上です。

この仕様をそのまま「プロジェクトの要求仕様」として生成AIに渡せば、

  • products.csv / history/*.csv の読み書き
  • PA-API のラッパ
  • 通知ロジック
  • GitHub Actions の YAML

まで一通り実装可能なレベルになっているはずです。