Google Custom Search APIを使った商品検索ツール開発メモ (Docker + Python)

# Google Custom Search APIを使った商品検索ツール開発メモ (Docker + Python)

## 概要
Google Custom Search APIを用いて、商品名をキーワードにウェブ検索し、その結果をExcelファイルとして出力するツールの開発メモです。  
Pythonスクリプトで処理を実装し、Dockerで環境構築・実行までを行いました。  
本記事では、開発中に直面した問題点やトラブルシューティングについてもまとめます。

## やりたいこと
- 任意のキーワード(商品名)でGoogle Custom Search APIを用いたウェブ検索
- 検索結果(URL, タイトル, 概要)をExcelファイル(`search_results.xlsx`)に出力
- Dockerコンテナ内でスクリプト実行 → ホスト側に結果を取得

## 使用技術・サービス
- 言語: Python
- ライブラリ: `requests`, `pandas`, `openpyxl`
- 環境: Docker
- API: [Google Custom Search JSON API](https://developers.google.com/custom-search/v1/overview)

## 環境構築フロー

1. **Google Custom Search APIキーとCX取得**
   - Google Cloud Platformでプロジェクト作成
   - [Programmable Search Engine](https://programmablesearchengine.google.com/)でウェブ全体検索が可能なCSEをセットアップ（`*`で全サイト検索）
   - APIキーとCXを控える

2. **Pythonスクリプト作成**
   `py/search_export.py` (例)
   ```python
   import requests
   import pandas as pd
   import argparse

   def main():
       parser = argparse.ArgumentParser(description="Google Custom Search Script")
       parser.add_argument("--api_key", required=True, help="Google Custom Search API key")
       parser.add_argument("--cx", required=True, help="Custom Search Engine ID")
       parser.add_argument("--query", required=True, help="Search query")

       args = parser.parse_args()

       API_KEY = args.api_key
       CX = args.cx
       query = args.query

       url = "https://www.googleapis.com/customsearch/v1"
       params = {
           "key": API_KEY,
           "cx": CX,
           "q": query,
           "hl": "ja",
           "lr": "lang_ja"
       }

       response = requests.get(url, params=params)
       data = response.json()

       items = data.get("items", [])
       results = []
       for item in items:
           title = item.get("title")
           link = item.get("link")
           snippet = item.get("snippet")
           results.append({"Title": title, "URL": link, "Description": snippet})

       df = pd.DataFrame(results)
       df.to_excel("search_results.xlsx", index=False)

   if __name__ == "__main__":
       main()

### 3. Dockerfile作成 (docker/Dockerfile)

```dockerfile
FROM python:3.11
WORKDIR /app
COPY py/search_export.py /app/
RUN pip install requests pandas openpyxl
CMD ["python", "search_export.py"]
```
ディレクトリ構成例:
```
product-usage-web-scraper/
  ├─ docker/
  │   └─ Dockerfile
  └─ py/
     └─ search_export.py
```

### 4. ビルド・実行例
```
cd product-usage-web-scraper
docker build -f docker/Dockerfile -t product-usage-web-scraper .
docker run -it product-usage-web-scraper python search_export.py \
    --api_key "YOUR_API_KEY" --cx "YOUR_CX" --query "牛丼"
```
### 5. 結果ファイル取得
バックグラウンド実行してコンテナID取得後にコピー:
```
docker run -d product-usage-web-scraper python search_export.py \
    --api_key "YOUR_API_KEY" --cx "YOUR_CX" --query "牛丼"
docker ps -a
# 最新のCONTAINER_IDを控える
docker cp <CONTAINER_ID>:/app/search_results.xlsx .
```
## トラブルシューティング

### CSE設定なのに期待した結果が出ない
- **原因**: CSEが特定サイト限定になっている可能性  
- **対策**: `*`を指定し全サイト検索可能にする。`hl=ja`や`lr=lang_ja`を付与して日本語検索を最適化

### `docker build`でCOPY失敗
- **原因**: ビルドコンテキストとファイルパスの不一致  
- **対策**: `docker build`を`product-usage-web-scraper`ディレクトリで実行し、`COPY py/search_export.py /app/`を正しく指定

### シェルスクリプト実行時`not found`エラー
- **原因**: Windows由来のCRLF改行コードが原因でUNIXシェルが正しく解釈できない  
- **対策**: `dos2unix`コマンドでLF改行へ変換する

### ファイル未生成(`docker cp`でファイルなし)
- **原因**: スクリプトエラーや`items`が空で`search_results.xlsx`未作成  
- **対策**: `docker logs <CONTAINER_ID>`でログ確認  
  `print(response.json())`をコードに追加しAPIレスポンスをチェック  
  APIキー・CX・CSE設定を再確認

### 結果が10件までしか取得できない
- **原因**: Custom Search APIは1リクエスト最大10件まで  
- **対策**: `start`パラメータを用いてページングし、複数回リクエストで件数拡張

### 料金について
- 1日100クエリまでは無料
- 超過分は1,000クエリあたり約5ドル程度 (最新情報要確認)

### まとめ
- Docker+PythonでGoogle Custom Search APIを利用し、ウェブ検索結果をExcel出力する一連のフローを構築
- 開発中の各種トラブル(改行コード、CSE設定、APIレスポンス確認)への対処法を記録
-  今後はエラー処理強化やページング対応などで機能拡張可能


これらの知見が、同様の開発を行う際の参考になれば幸いです。