ブログに戻ります

TikTokショップ価格追跡とPythonによる製品スナップショット

Daniel Kim
Daniel Kim

Lead Scraping Automation Engineer

01-Sep-2026

TL;DR:

  • 価格追跡はスナップショットパイプラインです。 scraper.tiktok.shop.pageをスケジュールで呼び出し、各応答にタイムスタンプを付け、同じものと比較します。
  • 比較キーには市場のコンテキストが含まれます。 商品ID、戻された地域、通貨、SKUのアイデンティティが誤った一致を防ぎます。
  • 商品とSKUの変更は異なるイベントです。 表示された商品の価格と在庫を、バリアントの可用性や価格とは別に追跡します。
  • 欠如はゼロではありません。 欠落しているフィールドは、品切れや自由価格のアラートを引き起こすべきではありません。
  • アクターは履歴やアラートを生成しません。 SQLiteストレージ、比較ルール、スケジューリング、配信は呼び出しアプリケーション内に存在します。
  • 無料で始められます。 新しいScrapelessアカウントは、Scrapeless Dashboardを通じて無料クレジットを含みます。

イントロダクション: トackerは繰り返しのリクエスト以上のもの

単一のTikTok Shop製品応答は、ページが現在公開している内容に回答します。価格トラッカーは異なる質問に答えます:2つの比較可能な観察間に何が変わり、その変化は誰かに通知するのに十分意味がありますか?

この区別は全体の設計に影響します。Scrapeless Shopアクターは構造化された製品スナップショットを提供します。アプリケーションはタイムスタンプを追加し、製品とSKUの行を保存し、各行を以前の観察と比較し、アラート準備が整ったイベントを発信します。このガイドは、PythonとSQLiteを使ってそのパイプラインを構築します。

製品スナップショットの背後にあるリクエストパターンについては、ライブのScrapelessデータアクターガイドをお読みください。

パイプラインの概要

ステージ アクション 永続的出力
フェッチ IDと地域で既知の製品をリクエスト 生のJSONスナップショット
ノーマライズ 製品とSKUフィールドを分離 比較可能な行
ストア タイムスタンプ付きの観察を挿入 製品とSKUの履歴
比較 前の一致記録を見つける 変更イベント
配信 ビジネスルールを適用 アラート準備が整ったJSON

このパイプラインは、アプリケーションが提供する製品リストを監視します。ショップ内のすべての製品を発見することや、プライベートオーダーレジャーを公開するものではありません。

前提条件

  • Scrapeless DashboardからのScrapelessアカウントとAPIトークン
  • 標準ライブラリとSQLiteサポートのあるPython
  • 公開されている既知のTikTok Shop製品ID
  • 各製品に対する地域ルール
  • どの変更が重要かを定義するアラートポリシー

コードには、SCRAPELESS_API_KEYにてライブトークンが必要です。製品リストはあなたのアプリケーションによって提供されます。

ステージ1 — 製品スナップショットを取得する

POST https://api.scrapeless.com/api/v1/scraper/requestをアクターscraper.tiktok.shop.pageと共に呼び出します。その入力には、product_idを文字列として、regionが含まれます。TikTok Shopページアクタードキュメンテーションは、リクエストと応答フィールドを示しています。

結果には、製品のアイデンティティ、戻された地域、販売者、名前、販売数、価格、通貨、在庫、評価、レビュー数、画像、オプション、SKU、カテゴリ、発送の詳細が含まれる場合があります。正規化の前に生の応答を保存しておくことで、後のスキーマ変更を同じ観察を再収集することなく処理できます。

ステージ2 — 製品およびSKU行の正規化

製品IDと戻された地域で作成された製品キーを使用します。バリアントについては、SKU識別子を追加します。通貨は比較記録に属し、数値価格は単独では安全なクロスマーケットの意味を持ちません。

ISO通貨コードのリファレンスは、通貨識別子の役割を説明しています。下流の報告レイヤーが価格を変換する場合でも、ソース値を保持します。

製品とバリアントの在庫は別々に保つべきです。TikTok Shopの在庫ドキュメンテーションは、製品とSKU識別子を異なるクエリディメンションとして扱い、クリーンスナップショットスキーマと一致します。

Scrapelessでスクレイピングを開始する

Scrapelessでウェブスクレイピングと自動化のワークフローを強化しましょう!
今すぐサインアップして**$5の無料クレジット**を入手 — クレジットカードは不要です。

Scrapeless Dashboardで今すぐ無料クレジットを請求してください。

ステージ3 — SQLiteにスナップショットを保存する

SQLiteは小規模なモニターに適しており、データベースと時間関数はPythonから別のサービスなしで使用できます。SQLite CREATE TABLEドキュメンテーションは、スキーマで使用されるテーブル制約を定義しています。

python Copy
import json
import os
import sqlite3
from datetime import datetime, timezone
from urllib.request import Request, urlopen

ENDPOINT = "https://api.scrapeless.com/api/v1/scraper/request"


def fetch_product(product_id, region):
    body = json.dumps({
        "actor": "scraper.tiktok.shop.page",
        "input": {"product_id": str(product_id), "region": region},
    }).encode()
    request = Request(
        ENDPOINT,
        data=body,
        headers={
            "x-api-token": os.environ["SCRAPELESS_API_KEY"],
            "content-type": "application/json",
        },
        method="POST",
    )
    with urlopen(request, timeout=60) as response:
        return json.load(response)


def open_database(path="tiktok_shop_history.sqlite3"):
    database = sqlite3.connect(path)
    database.execute("""
        CREATE TABLE IF NOT EXISTS product_snapshots (
            observed_at TEXT NOT NULL,
            product_id TEXT NOT NULL,
            region TEXT NOT NULL,
            currency TEXT,
            price TEXT,
            stock INTEGER,
            sold_count INTEGER,
            raw_json TEXT NOT NULL,
            PRIMARY KEY (observed_at, product_id, region)
        )
    """)
    return database


def store_product(database, raw):
    observed_at = datetime.now(timezone.utc).isoformat()
    row = (
        observed_at,
        str(raw.get("product_id", "")),
        str(raw.get("region", "")),
        raw.get("currency"),
        None if raw.get("price") is None else str(raw.get("price")),
        raw.get("stock"),
        raw.get("sold_count"),
        json.dumps(raw, ensure_ascii=False),
    )
    database.execute(
        "INSERT INTO product_snapshots VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
        row,
    )
    database.commit()
    return row

ストア価格は、サポートされているシステムにおいてソーステキストまたは正確な小数型として保存してください。バイナリ浮動小数点は、いくつかの10進数の値が正確に表現できないため、金銭の保存には不適切な選択です。

ステージ 4 — 前回の観察と比較

比較は、同じ product ID、返却地域、および通貨内でのみ行う必要があります。最も最近の以前の行を照会し、両方の観察に存在するフィールドのイベントを生成します。

python Copy
from decimal import Decimal


def previous_snapshot(database, product_id, region, observed_at):
    return database.execute(
        """
        SELECT observed_at, currency, price, stock
        FROM product_snapshots
        WHERE product_id = ? AND region = ? AND observed_at < ?
        ORDER BY observed_at DESC
        LIMIT 1
        """,
        (str(product_id), region, observed_at),
    ).fetchone()


def compare(current, previous):
    if previous is None:
        return {"state": "baseline", "changes": []}

    _, old_currency, old_price, old_stock = previous
    changes = []
    if current[3] == old_currency and current[4] is not None and old_price is not None:
        new_price = Decimal(current[4])
        prior_price = Decimal(old_price)
        if new_price != prior_price:
            changes.append({
                "field": "price",
                "before": str(prior_price),
                "after": str(new_price),
                "currency": current[3],
            })
    if current[5] is not None and old_stock is not None and current[5] != old_stock:
        changes.append({"field": "stock", "before": old_stock, "after": current[5]})
    return {"state": "compared", "changes": changes}


database = open_database()
raw = fetch_product(os.environ["TIKTOK_SHOP_PRODUCT_ID"], "GB")
current = store_product(database, raw)
prior = previous_snapshot(database, current[1], current[2], current[0])
print(json.dumps(compare(current, prior), indent=2))

最初の観察はベースラインを確立し、価格変更アラートを生成してはなりません。値が欠如している場合も、ゼロや在庫切れイベントにはなりません。

ステージ 5 — SKU 変更の追跡

観察時間、製品 ID、返却地域、および SKU ID でキー化された 2 番目の履歴テーブルを作成します。オプションラベル、公開されたときの SKU 価格、通貨、および可用性を保存します。SKU を自身の前の行とのみ比較します。

バリアントリストは変更される可能性があります。新たに観察された SKU は発見イベントであり、欠如した SKU はアプリケーションのコレクションポリシーに基づいて確認が必要な不在です。欠如した応答からバリアントを廃止することを宣言してはいけません。

ステージ 6 — アラート準備完了イベントを生成

コレクションを通知とは分けて管理します。比較ジョブは次のようなイベントを記録できます:

  • 同じ通貨と地域での製品価格が変更された
  • 集計在庫がビジネスの閾値を超えた
  • 知られた SKU の可用性が変更された
  • 新しい SKU が出現した

正確な変更が計算された後に閾値を適用します。以前の観察時間と現在の観察時間、製品 ID、地域、通貨、フィールド、および前後の値を含めます。ダウンストリームワーカーは、このイベントをメール、チャット、Webhook、または内部ダッシュボードにルーティングできます。

sold_count を注意深くお読みください

sold_count は、製品スナップショットとともに返却されたものとして保存します。これは、報告ウィンドウ、個別の注文、払い戻し、または GMV を特定するものではありません。観察間の変化はページラベルの変化であり、完全な売上元帳ではありません。

Scrapeless は、Scraping API を通じて製品アクターを提供します。製品セットと選択したスケジュールのコストを見積もるには、現在の価格ページ を使用してください。

結論:スナップショットを比較可能に保つ

TikTok ショップの価格追跡には、安定したキー、コレクションのタイムスタンプ、製品と SKU の履歴を分け、慎重な変更ルールが必要です。アクターは各公開製品のスナップショットを提供し、周辺の Python ジョブはそれらの観察を履歴およびアラート準備完了イベントに変換します。

価格モニターを構築する準備はできましたか?

Scrapeless Discord または Telegram コミュニティ に参加して、モニタリングスキーマについて話し合いましょう。製品リストとアラートポリシーが準備できたら、Scrapeless ダッシュボード にアカウントを作成してください。

FAQ

Q: Scrapeless は自動で TikTok ショップの価格履歴を提供しますか?

いいえ。アクターは製品スナップショットを返します。呼び出しアプリケーションはリクエストをスケジュールし、観察結果を保存、行を比較し、アラートを提供します。

Q: TikTok ショップの価格トラッカーはどのキーを使用すべきですか?

製品レコードには、製品 ID と返却地域を使用し、バリアントレコードには SKU ID を追加します。すべての価格比較に通貨を維持します。

Q: 欠如した価格または在庫値をゼロとして保存すべきですか?

いいえ。欠如は不明を意味し、ゼロは異なるビジネスの意味を持つ確定的な値です。

Q: 売上カウントを日次売上または GMV として使用できますか?

いいえ。返されたラベルは報告ウィンドウを構築せず、完全な受注と収益の元帳を提供しません。

Q: トラッカーはどれくらいの頻度で実行すべきですか?

ビジネスの決定、製品のボラティリティ、許可された使用、および予算に基づいて頻度を選択します。履歴のギャップが見えるようにスケジュールを記録します。

Q: 公開ショップ価格のモニタリングは法的に問題ありませんか?

合法性は管轄、マーケット、目的、アクセス方法、および適用される条件に依存します。許可された目的のために公開製品データを監視し、意図された利用のために法的助言を受けてください。

Q: プロキシ、ページ防御、または DOM セレクタを管理する必要がありますか?

Scrapeless はコレクション表面を管理します。アプリケーションは製品リスト、タイムスタンプ、ストレージ、比較、および通知を管理します。

Q: AI エージェントなしでこれを実行できますか?

はい。ワークフローは直接 HTTP リクエスト、SQLite、および通常の Python コードを使用します。

Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。

最も人気のある記事

カタログ