プロフィールやいくつかの好調な動画を見るとキャンペーンに適したクリエイターに思えても、最新のフィードからは、必要なテーマについて継続的に発信しているかという、より重要なことが分かります。手作業での確認はすぐに古くなり、一度だけ閲覧すると目立つ投稿だけを選びがちです。代理店やブランドには、公開動画を繰り返し取得できる形でサンプル化し、確認日時点の状態を保存したうえで、同じルールに基づいてテーマとの適合性を評価する方法が有用です。

以下では、TikTokクリエイターの公開フィードを評価する実用的な手順を紹介します。jsonscraperのTikTok Scraper APIとPythonを使い、文書化されたエンドポイントから投稿を取得して元のJSONを保存し、確認できたフィールドを表形式に整えて、指定テーマに合致する動画の割合を算出します。必要に応じて、次の段階として説明文をテキスト分類器に渡せます。この工程は独立させ、別途管理します。
まず「適合する」とは何かを定義する
たとえば、チームが家庭でのコーヒーの淹れ方をテーマにしたキャンペーンに起用するクリエイターを選ぶとします。フォロワー数や個々の動画の人気はリーチの把握に役立ちますが、それだけではフィードがコーヒーにどれほど関連しているかは分かりません。最初のスクリーニングでは、動画の説明文がコーヒーの抽出、器具、レシピ、レビューに触れているか、指定した観察期間にそのテーマの投稿が何件含まれているか、収集した投稿のうちテーマに関連するものがどれほどの割合を占めるか、といった内容の特徴が必要です。
データ収集の前に、基準を簡潔な語彙リストにまとめておきます。たとえば「エスプレッソ」「コーヒーグラインダー」「ラテ」「抽出」です。除外条件や曖昧な語も加えましょう。「コーヒー」は、冗談や広告案件、偶然の文脈で登場する場合があります。そのため、テキスト上の自動一致は初期ラベルであり、クリエイターに対する最終評価ではありません。少なくとも「明確に該当」「該当する可能性あり」「無関係」の3つに分類します。
サンプルの取り方も事前に決めておきます。たとえば、週次の実行ごとに取得できた直近20件を分析できます。これはモニタリング上の条件であり、APIが必ずその件数を返すという意味ではありません。取得できる内容や件数は、個々のリクエストへの応答によって決まります。異なるルールのスナップショットを混同せずに比較できるよう、収集時刻、取得件数、リクエストのパラメーターを記録してください。
クリエイターのフィードを取得する
jsonscraperのドキュメントによると、GET /getUserFeedエンドポイントでは、ユーザー名またはプロフィールURLを指定する必須パラメーターqueryを受け取ります。任意パラメーターとして、count、region、sort_type、with_pinned_posts、max_cursorが挙げられています。APIキーはlicense_keyとしてクエリ文字列で渡します。ソースコードではなく、環境変数に保存してください。エンドポイントとパラメーターの詳細は、公式TikTok APIドキュメントに記載されています。
応答では、まず外側のstatusを確認し、その後でtiktokオブジェクトを参照します。ユーザーフィードの投稿一覧はtiktok.aweme_listにあります。確認されたスキーマには、動画ID、説明文、投稿時刻、投稿者、URL、統計情報オブジェクトが含まれます。個々のフィールドが欠ける場合もあるため、処理側では空の値を、作り出した数値で補わずに空のまま保持してください。
次の最小限の例は、Python 3.8以降とrequestsライブラリを想定しています。キーをJSONSCRAPER_TIKTOK_LICENSE_KEYに保存します。コードは1回リクエストを行い、HTTP応答とAPIの外側ステータスを確認してから、元のJSONを書き出し、正規化した行を表示します。
import json
import os
from datetime import datetime, timezone
from pathlib import Path
import requests
API_KEY = os.environ["JSONSCRAPER_TIKTOK_LICENSE_KEY"]
PROFILE = "creator_username"
params = {
"license_key": API_KEY,
"query": PROFILE,
"count": 20,
"region": "US",
"sort_type": 0,
"with_pinned_posts": 0,
}
response = requests.get(
"https://tiktok.evelode.com/getUserFeed",
params=params,
timeout=30,
)
response.raise_for_status()
payload = response.json()
if payload.get("status") != "ok":
raise RuntimeError("TikTok API returned a non-ok status")
tiktok = payload.get("tiktok") or {}
items = tiktok.get("aweme_list") or []
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
Path("snapshots").mkdir(exist_ok=True)
Path(f"snapshots/{PROFILE}_{stamp}.json").write_text(
json.dumps(payload, ensure_ascii=False, indent=2),
encoding="utf-8",
)
rows = []
for item in items:
stats = item.get("statistics") or {}
author = item.get("author") or {}
rows.append({
"aweme_id": item.get("aweme_id"),
"created_at": item.get("create_time"),
"description": item.get("desc") or "",
"share_url": item.get("share_url"),
"creator": 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"),
})
print(json.dumps(rows, ensure_ascii=False, indent=2))
このエンドポイントのsort_typeは、0が新着順、1が人気順と説明されています。例では新着順を選び、with_pinned_posts=0で固定表示された投稿を除外しています。これにより、古い固定投稿が新しい投稿のサンプルに混ざるのを防げます。別のモードを使う場合は、スナップショットのメタデータにパラメーターを記録し、すべての実行で同じように適用してください。
応答を処理する:JSONから再現可能な表へ
変換する前に元の応答を保存しておくと便利です。正規化を再確認したり、ある行の値が空になった理由を調べたり、応答内の任意フィールドの有無が変化した際に処理を調整したりできます。本番環境のストレージでは、JSONとともに、UTCでの収集時刻、リクエストしたプロフィール、パラメーター、スクリプトのバージョンを保存します。APIキーをアーカイブやログに含めないでください。
繰り返し実行する場合は、フィールドが存在すればaweme_idを投稿の識別子として使います。このIDで重複を除去すれば、同じ動画を複数の投稿として数えることを防げます。一方、統計情報の各スナップショットは別々に保存してください。再生数やリアクションの値は観測時点のものであり、動画に固有の不変な特性ではありません。統計フィールドがない場合は空のままにし、その記録を該当指標の計算から除外します。
スキーマでは投稿時刻がcreate_timeで示されています。分析用の表では、これを日付に変換し、元の値と正規化したUTC時刻の両方を保存します。計算に入る前に、取得した応答から実際のレコードをいくつか確認し、想定どおりの型と単位かどうかを確かめてください。時系列グラフを作る際には特に重要です。時刻変換を誤ると、投稿が別の日に割り当てられ、週ごとの比較が損なわれます。
最小限のテーマ分類器は、モデルを使わずに構築できます。テキストを正規化し、指定したキーフレーズを検索して、一致を記録します。より実用的な分類には、人が確認した説明文のサンプルと、境界事例に対するルールを用意してください。そのうえで、単純な辞書フィルターの結果を人手の分類と比較し、誤検出につながる表現を特定して辞書を更新します。こうして、後からAIを適用する際に比較できる明確な基準値を作れます。
import re
KEYWORDS = (
"кофе", "эспрессо", "кофемолка", "латте", "заваривание",
)
def normalize(text):
text = (text or "").casefold()
return re.sub(r"\s+", " ", text).strip()
def classify(description):
text = normalize(description)
matches = [word for word in KEYWORDS if word in text]
return {
"topic_match": bool(matches),
"matched_terms": matches,
}
for row in rows:
row.update(classify(row["description"]))
説明文のキーワードは有用なシグナルですが、分類器には「はい/いいえ」のラベルだけでなく、一致した用語の一覧など、説明可能な理由も返させるとよいでしょう。言語モデルを使う場合は、構造化されたプロンプトを用意します。動画の説明文と固定のカテゴリーを渡し、カテゴリー、簡潔な根拠、確信度を返すよう求めてください。元のテキストとモデルの応答は別々に保存します。予算やパートナー選定に影響する判断は、投稿へのリンクをたどって人が確認してください。
分母が明確な指標を算出する
シンプルなレポートには、テーマに合致する動画の割合と投稿頻度が適しています。割合は、テーマに合致すると確認された動画の件数を、分類できた動画の件数で割って算出します。「確認した説明文18件のうち7件」のように、両方の数値を必ず示してください。そうすれば結果が分かりやすくなり、割合の基になったサンプルが少なすぎないかも判断できます。
投稿頻度は、たとえば直近30日間に取得した動画の件数として表せます。期間の境界は、収集時刻と公開日時に基づいて設定してください。週次でスナップショットを取る場合は、更新後の集計値だけでなく、各実行の結果を保存します。そうすれば、テーマや活動状況の変化を確認できます。取得件数をクリエイターの全投稿アーカイブとみなさず、実際に得られたサンプルを分析し、その抽出ルールを明示してください。
再生数、いいね、コメント、シェアの統計は、各動画の背景情報として役立ちます。絶対値を比較する際は慎重さが必要です。古い投稿のほうが、リアクションを蓄積する期間が長かった可能性があります。同じクリエイター内で比較する場合は、各収集時刻を記録し、同一動画のスナップショット間の推移を見ます。観測間隔と測定可能性が記録されていない場合、2つのスナップショットの差を「成長速度」と呼ばないでください。
各プロフィールの最終記録には、収集日、選択したパラメーター、取得した投稿数、分類した説明文の数、テーマに合致した件数、参考となるURLの一覧、曖昧な事例についての短いメモを含めると有用です。こうした表があれば、担当者が結論を確認でき、別の分析担当者も次のプロフィールで同じ手法を再現できます。
ページネーションとスケジュール
次のページが必要な場合、プロフィールフィードのドキュメントでは、前回の応答から取得したmax_cursorを使います。カーソルは変換せずに渡してください。APIに保存して返す不透明な値です。続きの取得を予定している場合は、応答内のhas_moreも確認します。収集が予測可能に完了するよう、ページ数またはリクエスト総数に上限を設定してください。
cursor = None
all_items = []
max_pages = 3
for _ in range(max_pages):
page_params = dict(params)
if cursor is not None:
page_params["max_cursor"] = cursor
page_response = requests.get(
"https://tiktok.evelode.com/getUserFeed",
params=page_params,
timeout=30,
)
page_response.raise_for_status()
page_payload = page_response.json()
if page_payload.get("status") != "ok":
raise RuntimeError("TikTok API returned a non-ok status")
page = page_payload.get("tiktok") or {}
all_items.extend(page.get("aweme_list") or [])
if not page.get("has_more"):
break
cursor = page.get("max_cursor")
if cursor is None:
break
実行頻度は目的に合わせて選びます。初期評価なら手動実行で十分です。クリエイターの一覧を扱う場合は、週次実行にすると、継続的な問い合わせを避けながら変化を把握できます。cron、CIタスク、オーケストレーターのいずれにも組み込めます。流れはシンプルです。表からプロフィールを取得し、並列数を制限してリクエストを実行し、スナップショットを保存し、成功応答の割合を確認して、概要を作業用の表に送ります。一時的なエラーには、回数と待機時間に上限を設けて再試行してください。認証済みリクエストのエラーは別に記録し、キーや設定を確認できるようにします。
AIの活用が適切な場面と、人の確認が必要な場面
スラング、複数の言語、正確なキーワードを含まない表現が説明文に含まれる場合、AIは分類に役立ちます。まず、選択肢を限定したカテゴリー一覧を定め、モデルには説明文のテキストだけを使うよう指示してください。次に、人手でラベル付けした少量のサンプルで品質を測定します。モデルのカテゴリーを編集者の判断と比較し、誤りや曖昧な事例を個別に検討してください。レポートには、解釈しにくい総合スコアではなく、人手の分類とモデルが一致した割合、および確認した事例数を含めるとよいでしょう。
基準を示さずに「最適なクリエイターを選んで」とモデルに任せないでください。代わりに、テーマ該当率、投稿頻度、関連動画の例、公開されているリアクションの範囲といった測定可能な要素に分けます。モデルにそれらの項目を簡潔に要約させ、根拠となるリンクを示させることはできます。最終判断は、キャンペーンの形式、オーディエンス、クリエイターとの合意事項を考慮するチームが行います。
広告案件を分析する場合は、投稿そのものと適用される要件に照らして、クリエイターとブランドの関係が開示されているかを別途確認してください。米国連邦取引委員会のガイドラインは、ブランドとの関係を推奨表現の近くに明確に開示する必要があると説明しています。プロフィール欄や、見えにくいテキスト部分だけでは、オーディエンスに分かりやすく知らせるには不十分な場合があります。FTCのソーシャルメディア・インフルエンサー向けガイダンスを参照してください。公開データのモニタリングは確認のための資料を集めるのに役立ちますが、ルールへの準拠を評価するには、個々の投稿やキャンペーンの文脈が必要です。
最終的に得られるもの
パイプラインを整備すると、チームは日付付きの公開フィードのスナップショット、説明文と利用可能な指標を含む投稿一覧、再現可能なテーマ該当率の計算結果を得られます。これらを基に、さらに確認するプロフィールの選定を効率化し、テーマの変化を把握して、評価の根拠を記録できます。この手法は検証可能です。元のJSON、リクエストのパラメーター、分類ルール、動画へのリンクをたどれば、データから結論に至るまでの過程を確認できます。
最初のテストでは、1つのプロフィールに対してスクリプトを実行し、元の応答を保存して、分類結果をいくつか手作業で確認します。次に、テーマ語彙、サンプルのルール、レポートの形式を固定します。結果が再現可能になったら、スケジュールとプロフィールのキューを追加してください。エンドポイントとパラメーターの説明はAPIドキュメントで、製品概要と利用可能な統合方法はTikTok Scraper APIのページで確認できます。
実行前の実用チェックリスト
- キャンペーンのテーマ、対象語の辞書、境界事例の例を記録する。
- サンプル期間、
countの値、並べ替え方法、固定投稿の設定を明記する。 - 元のJSON、収集日、パラメーターを、秘密情報であるAPIキーとは分けて保存する。
- 識別子が存在する場合は
aweme_idを使って重複を除去する。 - 値がない場合とゼロを区別し、明確な根拠なしに指標を平均しない。
- テーマ該当率とともにサンプル数を示し、例となる投稿へのリンクを添える。
- キャンペーンの判断に使う前に、人手のサンプルでAI分類を検証する。
- スケジュールに沿って評価を更新し、同じルールで収集したスナップショットを比較する。