活用シーンとソリューション

AI で商品説明文を多言語で一括生成:CSV の商品情報からタイトル・箇条書き・説明文を作成

6 ステップ 12 分で読めます 68 回閲覧 0
目次

越境 EC の販売者は、同じ商品を Shopee、Lazada、Amazon、TikTok Shop、自社ストアに複数の言語で出品することがよくあります。言語モデルを使えば、商品情報をまとめたスプレッドシートから、数百点分のタイトル、箇条書き、商品説明の下書きを一晩で作成できます。この記事では、CSV ファイルを読み込み、Ollama のローカルモデル(または OpenAI 互換の任意の AI API)に言語ごとの商品ページを生成させ、結果を新しい CSV ファイルに書き出す小さな Python スクリプトを作成します。書き出した結果は内容を確認したうえで、各マーケットプレイスのテンプレートにインポートします。

AI が作成した下書きは、公開前に必ず確認してください。モデルは実在しない機能を書き加えたり、医療的な効能表示や「世界最高」のように、マーケットプレイスで禁止されている表現を使ったりすることがあります。特に規制のあるカテゴリーでは必ず人によるチェックを挟み、各マーケットプレイスの出品ルールに従ってください。

ステップ1:商品情報を準備する

1 商品 1 行のスプレッドシートを作成し、UTF-8 で products.csv として保存します(Excel では CSV UTF-8 形式を選択)。列名は自由で、すべての列がモデルに渡されますが、スクリプトには一意の sku 列が必要です。

sku,name,category,specs,keywords
LS-01,Bamboo laptop stand,Office,"6 height levels; fits 10-17 inch laptops; foldable; 1.1 kg; natural bamboo","laptop stand, bamboo, ergonomic"
BT-07,Wireless earbuds,Audio,"Bluetooth 5.3; 30 h playback with case; IPX5; USB-C charging","wireless earbuds, bluetooth, sport"

スクリプトはモデルにこれらの情報だけを使うよう指示するため、素材、サイズ、対応機種、同梱物などの商品情報が正確であるほど、より良く、より安全な結果が得られます。

ステップ2:スクリプトの実行環境をインストールする

apt install -y python3-venv
python3 -m venv /opt/listing
/opt/listing/bin/pip install openai

openai Python ライブラリは Ollama の OpenAI 互換エンドポイントにも、ほとんどの AI プロバイダーにも対応しているため、同じスクリプトをローカルモデルでもクラウドモデルでも実行できます。Ollama のセットアップは「Ollama でローカル LLM を運用する」で解説しています。

ステップ3:スクリプトを作成する

cat > /opt/listing/listing.py <<'EOF2'
import csv, json, os, re, sys, time
from openai import OpenAI

client = OpenAI(base_url=os.environ.get("AI_BASE_URL", "http://127.0.0.1:11434/v1"),
                api_key=os.environ.get("AI_API_KEY", "ollama"))
MODEL = os.environ.get("AI_MODEL", "qwen2.5:7b")
LANGS = [l.strip() for l in os.environ.get("LANGS", "English").split(",")]

SYSTEM = """You write e-commerce product listings for online marketplaces.
Use only the product facts provided. Never invent features, materials,
certifications, prices or delivery promises. No exaggerated claims.
Return JSON only, in this format:
{"title": "...", "bullets": ["...", "...", "...", "...", "..."], "description": "..."}
title: at most 120 characters, main keyword first.
bullets: 5 short points, each starting with the benefit.
description: 80 to 150 words of plain text."""

def ask(product, lang):
    prompt = f"Write the listing in {lang}.\nProduct facts:\n{json.dumps(product, ensure_ascii=False)}"
    for attempt in range(3):
        r = client.chat.completions.create(model=MODEL, temperature=0.4, messages=[
            {"role": "system", "content": SYSTEM}, {"role": "user", "content": prompt}])
        m = re.search(r"\{.*\}", r.choices[0].message.content or "", re.S)
        try:
            data = json.loads(m.group(0))
            if data.get("title") and isinstance(data.get("bullets"), list) and data.get("description"):
                return data
        except (AttributeError, ValueError):
            pass
        time.sleep(2)
    raise RuntimeError(f"no valid answer for {product['sku']} / {lang}")

src, dst = sys.argv[1], sys.argv[2]
done = set()
if os.path.exists(dst):
    with open(dst, encoding="utf-8-sig") as f:
        done = {(r["sku"], r["language"]) for r in csv.DictReader(f)}
with open(src, encoding="utf-8-sig") as f:
    products = list(csv.DictReader(f))

new_file = not os.path.exists(dst)
with open(dst, "a", newline="", encoding="utf-8-sig") as f:   # utf-8-sig: Excel shows every language correctly
    w = csv.writer(f)
    if new_file:
        w.writerow(["sku", "language", "title", "bullets", "description"])
    for p in products:
        for lang in LANGS:
            if (p["sku"], lang) in done:
                continue
            d = ask(p, lang)
            w.writerow([p["sku"], lang, str(d["title"]).strip(),
                        "\n".join(str(b).strip() for b in d["bullets"]), str(d["description"]).strip()])
            f.flush()
            print(p["sku"], lang, "done", flush=True)
EOF2

スクリプトは JSON 形式で回答を求めて内容を検証し、最大 3 回まで再試行します。完成した行はすぐに書き込まれ、2 回目以降の実行では出力ファイルにすでにある商品と言語の組み合わせをスキップします。そのため、ジョブが中断しても、止まったところから処理を再開できます。

ステップ4:実行する

cd /data/listings
LANGS="English,Thai,Malay,Japanese" nohup /opt/listing/bin/python /opt/listing/listing.py \
  products.csv listings.csv > listing.log 2>&1 &
tail -f listing.log

CPU サーバーでは 7B モデルで 1 件あたり通常数十秒かかるため、500 商品を 4 言語で生成すると一晩がかりの処理になります。代わりにクラウドモデルを使う場合は、OpenAI 互換 API のアドレス、キー、モデル名を指定します。

AI_BASE_URL=https://ai.example.com/v1 AI_API_KEY=sk-your-key AI_MODEL=cloud-chat \
LANGS="English,Thai" /opt/listing/bin/python /opt/listing/listing.py products.csv listings.csv

AI プロバイダーは、サービス提供対象の地域から利用規約の範囲内で使用してください。

ステップ5:確認してインポートする

  1. listings.csv を Excel または Google スプレッドシートで開き、言語でフィルターします。
  2. タイトルの文字数を各マーケットプレイスの上限と照らし合わせ、内容が仕様と一致しているかを抜き取りで確認します。
  3. 売れ筋商品については、少なくとも一度はネイティブスピーカーに確認してもらい、文体が適切かどうかを確かめます。
  4. 各列をマーケットプレイスごとの一括アップロード用テンプレートにコピーします。列名はプラットフォームによって異なります。

ステップ6:生成結果の品質を高める

  • ブランドのトーンやマーケットプレイスのルールを SYSTEM に追加します。たとえば、使用しない単語のリスト、イギリス英語かアメリカ英語か、絵文字を使わない、などです。
  • 承認済みの商品ページを 1 件、例として SYSTEM に貼り付けます。モデルはその構成とトーンをかなり忠実に再現します。
  • qwen2.5:14b のような大きなモデルは、タイ語、マレー語、ベトナム語の文章が目に見えて良くなりますが、その分速度が落ち、メモリも多く消費します。
  • カタログ全体で同じモデルとプロンプトを使い続けると、すべての商品ページの文体を統一できます。

よくある質問

AI で作成した商品ページは、マーケットプレイスや検索エンジンで不利になりますか?

マーケットプレイスが重視するのは正確さとポリシーの遵守、検索エンジンが重視するのはコンテンツが役に立つかどうかです。人が確認した正確で具体的な商品ページであれば問題ありません。誤りや根拠のない主張を含む大量生産の文章は、誰が書いたかに関係なくリスクになります。

スクリプトが「no valid answer」で停止する

モデルが 3 回続けて有効な JSON ではない応答を返しています。同じコマンドをもう一度実行する(続きから再開されます)か、temperature を下げるか、より大きなモデルを使ってください。

商品画像の準備にも AI を使えますか?

はい。商品を切り抜いて白背景のメイン画像を一括作成する方法は「rembg で商品画像の背景を一括削除する」を参照してください。

上記の手順で解決しない場合は、サポートチケットを送信して IMIDC の 24 時間 365 日対応テクニカルサポートへご連絡ください。サーバー IP、使用しているモデル、実行したコマンド、listing.log の末尾数行を添えていただくと、より迅速に調査できます。

この回答はお役に立ちましたか?

関連チュートリアル