サポートチームには、わかりにくい機能について話したり、製品に関する質問をしたりしている公開TikTok動画の一覧が必要です。手作業の検索は同じ手順で繰り返すのが難しく、検索APIのレスポンスでは動画が異なるJSONの場所に格納されている場合があります。以下の最小限のPythonスクリプトは、キーワードで結果を取得し、2つの構造を統合し、IDで重複を除去して、見つかったレコードをCSVに保存します。
スクリプトで得られる結果
出力される表には、動画ID、リンク、説明、投稿時刻、作者、取得可能な反応数が含まれます。サポートやマーケティングの担当者は、回答や手順の更新、社内CRMでの確認が必要なトピックを手作業で記録できます。この表は、指定した検索語に対してAPIが返した結果を示すものです。すべての議論を網羅したカタログではなく、確認用の作業サンプルとして扱ってください。

このスクリプトが行うのは、収集と初期整理です。説明文が質問なのか、苦情なのか、冗談なのかを自動判定するものではありません。こうしたラベルは、手作業で確認した後に付けるか、別の分類器を使って付与するのが適切です。その際は、元のテキストと判定理由を記録してください。
検索内容とレスポンスの構造
jsonscraperは、https://tiktok.evelode.comをホストとするGETルート/searchVideoを、動画検索用として案内しています。必須パラメーターはkeywordです。count、地域、並べ替え、投稿期間、次ページ用カーソルも指定できます。たとえば、機能名、よく使われるエラーの表現、設定に関する短い質問など、あらかじめ決めた複数の語句で検索を繰り返せます。パラメーターと指定可能な値は、TikTok APIリファレンスに記載されています。
パーサーで注意すべき点があります。検索結果のaweme_list配列が空でも、見つかったオブジェクトがsearch_item_listに格納され、その各要素の中にaweme_infoがある場合があります。そのため、以下の処理では両方の形式を確認します。2026年10月25日の確認時に観察されたレスポンス例とフィールドは、jsonscraperの一次仕様書に記載されています。統計フィールドが存在しない場合もあるため、このコードは値を捏造して補いません。
キーと検索語リストを準備する
キーはソースファイルに記述せず、環境変数JSONSCRAPER_TIKTOK_LICENSE_KEYに保存します。LinuxまたはmacOSのシェルでは、次のように設定できます。
export JSONSCRAPER_TIKTOK_LICENSE_KEY="あなたのキー"
requestsライブラリをインストールし、1行に1つの検索語を記したqueries.txtを用意します。例として、製品名 設定方法や機能名 動作しないなどを記載します。対象ユーザーの言語に合わせて検索語を選び、週次のデータ取得で同じ語句を比較できるよう、別のリストとして管理してください。
python -m pip install requests
見つかった動画を収集して正規化する
この例はPython 3.8以降に対応しています。各検索語について結果数を制限して1回ずつリクエストを送り、HTTPエラーと上位ステータスを確認したうえで、実際に存在するフィールドだけを保存します。重複した結果はaweme_idで統合し、動画が見つかったすべての検索語をkeywordsフィールドに記録します。collected_at_utcフィールドにはデータ取得時刻を記録し、次回の実行結果と比較できるようにします。

import csv
import os
import sys
from datetime import datetime, timezone
import requests
BASE_URL = "https://tiktok.evelode.com/searchVideo"
API_KEY = os.environ.get("JSONSCRAPER_TIKTOK_LICENSE_KEY")
if not API_KEY:
raise SystemExit("JSONSCRAPER_TIKTOK_LICENSE_KEYを設定してください")
def get_items(tiktok):
"""検索レスポンスで文書化された2つの形式から動画を抽出する。"""
items = list(tiktok.get("aweme_list") or [])
for entry in tiktok.get("search_item_list") or []:
info = entry.get("aweme_info") if isinstance(entry, dict) else None
if info:
items.append(info)
return items
with open("queries.txt", encoding="utf-8") as query_file:
queries = [line.strip() for line in query_file if line.strip()]
collected_at = datetime.now(timezone.utc).isoformat()
videos = {}
for keyword in queries:
response = requests.get(
BASE_URL,
params={
"license_key": API_KEY,
"keyword": keyword,
"count": 30,
"region": "US",
"sort_by": "relevance",
},
timeout=30,
)
response.raise_for_status()
payload = response.json()
if payload.get("status") != "ok":
print("APIステータスが失敗を示しています。検索語:", keyword, file=sys.stderr)
continue
tiktok = payload.get("tiktok") or {}
for item in get_items(tiktok):
video_id = item.get("aweme_id")
if not video_id:
continue
if video_id not in videos:
author = item.get("author") or {}
stats = item.get("statistics") or {}
videos[video_id] = {
"aweme_id": video_id,
"keywords": [keyword],
"description": item.get("desc"),
"share_url": item.get("share_url"),
"create_time": item.get("create_time"),
"author": author.get("unique_id") or author.get("nickname"),
"play_count": stats.get("play_count"),
"digg_count": stats.get("digg_count"),
"comment_count": stats.get("comment_count"),
"share_count": stats.get("share_count"),
"collected_at_utc": collected_at,
}
elif keyword not in videos[video_id]["keywords"]:
videos[video_id]["keywords"].append(keyword)
columns = [
"aweme_id", "keywords", "description", "share_url", "create_time",
"author", "play_count", "digg_count", "comment_count", "share_count",
"collected_at_utc",
]
with open("tiktok_support_review.csv", "w", newline="", encoding="utf-8-sig") as output:
writer = csv.DictWriter(output, fieldnames=columns)
writer.writeheader()
for video in videos.values():
row = dict(video)
row["keywords"] = " | ".join(row["keywords"])
writer.writerow(row)
print("保存された重複のない動画数:", len(videos))
リクエストはparamsパラメーター経由で送信されるため、ライブラリが検索語をURL内で適切にエンコードします。ドキュメントの説明どおり、キーはクエリパラメーターに含まれるため、リクエストの完全なURLをアプリケーションログに出力しないでください。診断にはHTTPレスポンスコード、検索語、実行時刻を記録し、秘密情報や用途に不要な個人データは除外します。
誤った解釈を避けてCSVを読む
keywords列には、動画が見つかったすべての検索語が含まれます。collected_at_utcによって、投稿時刻と収集時刻を区別できます。IDは重複排除に、リンクは人による確認に役立ちます。カウンターが空欄の場合、そのレスポンスにフィールドがなかったことを意味し、値がゼロだったという意味ではありません。
最初の仕分けでは、CSVの作業用コピーにトピック、シグナルの種類、回答が必要、社内資料へのリンクの列を追加します。トピックの選択肢は、インストール、支払い、互換性、エラー解決など、製品に即したものにしてください。この方法で収集データを確認キューに変え、元の動画に基づいて判断を検証できる状態に保てます。
定期実行を設定する
まずスクリプトを手動で実行し、数行分の内容とリンクを確認します。その後、cron、CIタスク、またはPythonプロセスを実行できる自動化シナリオに追加します。定期レポートを作成する場合は、取得ごとのファイルを保存するか、動画IDとスナップショット日付を一意キーとしてデータストアに行を追加してください。こうすれば、チームは新たに見つかった投稿と以前の実行で再び観測された投稿を区別し、取得可能なカウンターが実行ごとにどう変化したかを追跡できます。
cursorパラメーターは検索結果のページ送りに用意されており、前回の呼び出しのレスポンスから渡す必要があります。この最小例では、意図的にページネーションを省いています。検索語を限定したほうが、確認や再現が容易だからです。ページを追加する場合はカーソルを不透明な値として扱い、続きの有無を示すフラグに従って停止し、1回の実行あたりの呼び出し数に上限を設けてください。APIリクエストが返すのはサンプルであり、行数をTikTok全体の網羅性と解釈しないでください。
利用上の実務的な制約
検索結果は、チームがすでに把握している表現を使って動画を見つけるのに適しています。分類用の素材を集める助けにはなりますが、受信した問い合わせ、自社サイトの分析、動画の文脈確認に取って代わるものではありません。説明文に動画の要点が含まれていない場合もあり、利用可能な指標はデータ取得時点の状態を示します。分類を後から見直せるよう、トピックや判断は元のフィールドとは別に記録してください。
定期的なモニタリングを始める前に、誰がデータ取得結果にアクセスできるか、データをどれだけの期間保存するか、公開情報をどの目的で使うかを決めてください。製品の確認に必要なフィールドだけを保存し、メディアファイルを複製するより、元の投稿へのリンクを利用するようにします。リクエスト方法や利用可能な連携手段を確認するには、TikTok Scraper APIのページと検索ルートのドキュメントを参照してください。