לאחר השקת קמפיין, הצוות עשוי לרצות לבדוק אילו סרטונים ציבוריים מופיעים בתוצאות החיפוש עבור מילים נבחרות. קשה לחזור על חיפוש ידני ולהשוות את התוצאות כעבור כמה ימים. אוסף נתונים קטן יכול להריץ את אותן בקשות לפי לוח זמנים ולארכב את התגובות עם תאריך ומונח חיפוש, כדי שאנליסט יוכל לבדוק את הרשומות ולהכין סיכום משלו.

במדריך הזה מוצג צינור עבודה לארכוב תוצאות חיפוש של ביטויים קבועים באמצעות Python. בניגוד לניטור של האשטגים או חשבונות מסוימים, המפתח להשוואה כאן הוא חזרה על אותם ביטויי חיפוש ושמירת תמונת מצב נפרדת לכל תגובה. בדף TikTok Scraper API של jsonscraper מצוינים כתובת הבסיס והנתיב GET /searchVideo; בתיעוד הנתיב הזה, ביטוי החיפוש מועבר בפרמטר החובה keyword.
המטרה וגבולות המדידה
נניח שמשווק רוצה לאסוף מדי יום תוצאות עבור כמה ביטויים קבועים: שם מוצר, קטגוריה וניסוח של בעיית לקוח. עבור כל בקשה, המערכת שומרת את זמן האיסוף ואת תגובת ה-API. לאחר בדיקת דוגמת תגובה אפשר להוסיף נרמול של שדות שנמצאים בפועל ב-JSON, כגון מזהה סרטון או מונים ציבוריים, אם הם מופיעים בו.
הארכיון עונה על שאלה ממוקדת: אילו רשומות החיפוש החזיר עבור הביטוי השמור במהלך ההרצה הזאת? אם התגובה כוללת מדדים, תצפיות חוזרות עשויות להראות את ההבדל בין ערכים שנרשמו במועדים שונים. ההבדל מתייחס לתמונות המצב שנצפו ולמרווח הזמן ביניהן; לצורך השוואה שמרו את שני זמני האיסוף ואת אותו שדה.
שמרו את הבקשה יחד עם התגובה. הרכב התוצאות קשור לביטוי חיפוש מסוים ולמועד האיסוף. לכן הארכיון מועיל למעקב אחר תוצאות עבור שאילתות נבחרות, אך אינו סקירה מלאה של כל התוכן ב-TikTok. מזהים, תגובות מקוריות וחותמות זמן מסייעים לבדוק מה מקורו של כל שורה בטבלה שתופק בהמשך.
בדקו את הנתיב ואת הפרמטרים שלו
מפת הנתיבים של TikTok API מציינת את כתובת הבסיס https://tiktok.evelode.com ואת GET /searchVideo. מפרט ה-API העדכני מגדיר את keyword כפרמטר חובה לחיפוש; הפרמטרים האופציונליים המפורטים הם cursor, count, cache_timeout, date_posted, sort_by ו-region. לצורך אימות משתמשים ב-license_key. פרטים על הנתיב זמינים גם ב-תיעוד Python SDK.
הפרמטרים count ו-date_posted מסייעים לקבוע את גודל התגובה ואת מסנן הזמן; sort_by מקבל את הערכים המתועדים most-liked, relevance או date-posted. אם משתמשים בדפדוף, העבירו את cursor שהתקבל בתגובה הקודמת כערך אטום, מבלי לחשב אותו בעצמכם. לשם ארכיון יומי שניתן להשוואה, שמרו לצד הנתונים את פרמטרי הבקשה ואת גרסת הקוד שלכם.
בדוגמה שלהלן נעשה שימוש בערך קטן של count להרצת בדיקה ובאזור קבוע, US. לפני האיסוף היומי בדקו בקשה אחת, את סטטוס ה-HTTP שלה ואת מבנה ה-JSON. סכמת התגובה עשויה לכלול סרטונים שנמצאו ב-tiktok.aweme_list או ב-tiktok.search_item_list, שבה האובייקט של הסרטון נמצא ב-aweme_info; הקוד תומך בשתי הצורות שנצפו.
הכנת הפרויקט
צרו סביבה וירטואלית והתקינו את requests:
python -m venv .venv
source .venv/bin/activate
pip install requests
ב-PowerShell מפעילים את הסביבה באמצעות הפקודה .venv\Scripts\Activate.ps1. הגדירו את המפתח ואת רשימת ביטויי החיפוש באמצעות משתני סביבה. עבור TikTok API השתמשו בשם המשתנה המתועד JSONSCRAPER_TIKTOK_LICENSE_KEY:
export JSONSCRAPER_TIKTOK_LICENSE_KEY="המפתח_שלכם"
export TIKTOK_QUERIES="שם המוצר,קטגוריית המוצר,בעיית הלקוח"
איסוף ושמירת תמונות מצב
הדוגמה שולחת בקשה אחת לכל ביטוי לנתיב המתועד, ואז שומרת את ה-JSON המקורי, את זמן האיסוף ואת הפרמטרים ששימשו. שם הקובץ כולל את התאריך ואת ביטוי החיפוש. המפתח נשמר בסביבת העבודה ואינו נכלל בארכיון.
import json
import os
import re
import time
from datetime import datetime, timezone
from pathlib import Path
import requests
BASE_URL = "https://tiktok.evelode.com"
ENDPOINT = "/searchVideo"
LICENSE_KEY = os.environ["JSONSCRAPER_TIKTOK_LICENSE_KEY"]
QUERIES = [
item.strip()
for item in os.environ["TIKTOK_QUERIES"].split(",")
if item.strip()
]
OUT = Path("data")
OUT.mkdir(exist_ok=True)
def safe_name(text):
cleaned = re.sub(r"[^a-zA-Z0-9_-]+", "_", text).strip("_")
return cleaned[:80] or "query"
def fetch(query):
params = {
"license_key": LICENSE_KEY,
"keyword": query,
"count": 10,
"region": "US",
}
response = requests.get(
BASE_URL + ENDPOINT,
params=params,
timeout=60,
)
response.raise_for_status()
payload = response.json()
if payload.get("status") != "ok":
raise RuntimeError("ה-API החזיר סטטוס שאינו ok")
return payload
def extract_videos(payload):
tiktok = payload.get("tiktok") or {}
videos = list(tiktok.get("aweme_list") or [])
for item in tiktok.get("search_item_list") or []:
video = item.get("aweme_info") or {}
if video:
videos.append(video)
return videos
for query in QUERIES:
collected_at = datetime.now(timezone.utc).isoformat()
payload = fetch(query)
record = {
"collected_at": collected_at,
"query": query,
"request": {
"endpoint": ENDPOINT,
"keyword": query,
"count": 10,
"region": "US",
},
"videos_found": len(extract_videos(payload)),
"payload": payload,
}
filename = OUT / f"{collected_at[:10]}_{safe_name(query)}.json"
filename.write_text(
json.dumps(record, ensure_ascii=False, indent=2),
encoding="utf-8",
)
print(f"נשמרה תגובה עבור השאילתה: {query}")
time.sleep(1)
print(f"מספר התגובות שנשמרו: {len(QUERIES)}")
האוסף המצומצם הזה שולח בקשה אחת לכל ביטוי, עם count=10. כדי לאסוף היקף רחב יותר, הוסיפו דפדוף באמצעות cursor: המשיכו לשלוח בקשות ולהעביר את ערך הסמן מהתגובה, כל עוד ה-API מציין שקיימות תוצאות נוספות, ושמרו כל תגובה בנפרד. הסמן ומספר התוצאות מגדירים מעבר מסוים; ה-JSON השמור מאפשר לבדוק בדיעבד בדיוק מה הוחזר בכל בקשה.
הדוגמה בודקת את status החיצוני ואז קוראת את אובייקט tiktok. היא אוספת פריטים מתוך aweme_list, וכן מתוך search_item_list[].aweme_info אם הצורה הזאת קיימת. שדות אפשריים של סרטון כוללים מזהה, תיאור, מחבר, קישור ונתונים סטטיסטיים; ייתכן ששדות מסוימים לא יופיעו. לכן שמרו את התגובה המלאה ובדקו שכל שדה קיים לפני הנרמול.
מרווח של שנייה הוא השהיה בין הבקשות של הסקריפט עצמו, ולא הצהרה על מגבלות השירות. הגדירו את תדירות הבקשות ואת הניסיונות החוזרים בהתאם לתנאי הגישה ולתיעוד. הפרמטר cache_timeout מתועד עבור חיפוש; הוא מאפשר להגדיר את משך השמירה במטמון בשניות, ולפי המפרט הערך 0 משבית אותה. הוסיפו אותו לבקשה כאשר ההתנהגות הזאת מתאימה לתרחיש שלכם.
הוסיפו נרמול על סמך התגובה בפועל
לאחר ההרצה הראשונה פתחו את הקובץ שנשמר ובדקו את מבנה payload. הפונקציה extract_videos בדוגמה אוספת פריטים משני המקומות המתועדים שבהם עשויים להופיע סרטונים בתגובת החיפוש. מצאו את שמות המפתחות המדויקים של השדות הדרושים לניתוח. אם שדה חסר ברשומה מסוימת, שמרו אותו כערך חסר במקום להציב מספר משוער.
לעיבוד נוסף, נוח ליצור שורה אחת לכל אובייקט שנמצא ולהוסיף לו את collected_at ואת query. אפשר לשמור שדות שאומתו ב-CSV או במסד נתונים, ולהשאיר את ה-JSON המקורי בארכיון. שילוב כזה מאפשר לבנות טבלאות נוחות ובו בזמן לבדוק את מקורן של הרשומות.
אם ה-API מחזיר מזהה סרטון, השתמשו בו כדי לקשר בין תצפיות של אותו סרטון בהרצות שונות. שמרו כל תצפית בנפרד ואל תדרסו נתונים קודמים. אם אין מזהה יציב, בדקו תחילה אילו מאפיינים מאפשרים להתאים בין הרשומות, ואל תניחו שהופעה של אותו טקסט תיאור מבטיחה התאמה.
השוו תמונות מצב והכינו דוח
לאחר הנרמול, קבצו רשומות לפי מזהה שנבדק ומיינו אותן לפי זמן האיסוף. אפשר לחשב בקוד רגיל את ההפרש בין שני ערכים עוקבים בשדות של מונים. לדוגמה, מעבר מ-12,400 ל-18,900 פירושו שערך המונה השתנה ב-6,500 בין שתי תמונות המצב. ציינו בדוח את מועדי התצפיות ואת שדה המקור, כדי שהקורא יוכל לבדוק את החישוב.
מבנה שימושי של טבלת סיכום כולל את ביטוי החיפוש, מזהה הפרסום, זמן האיסוף ושדות נבחרים מהתגובה. אפשר לקבץ את הסיכום לפי שאילתות ולמיין לפי מונה אחד שאומת. כך יקבל הצוות רשימה בדיקה של הרשומות שהוחזרו, להמשך עיון; את הטבלה או ההודעה יש להפיק בשלב נפרד, לאחר בדיקת הסכמה בפועל.
בתחילה שמרו את קובצי ה-JSON באופן מקומי. כשהאיסוף יהפוך לשגרתי, העבירו את השורות המנורמלות ל-PostgreSQL או למחסן נתונים, ואת התגובות המקוריות לאחסון אובייקטים שבו שם הקובץ כולל את התאריך והשאילתה. שמירת המקור מועילה במיוחד כשמעדכנים את המנתח: אפשר להריץ אותו שוב על נתונים היסטוריים בלי לפנות שוב ל-API.
תזמנו את האיסוף
לארכיון יומי, הפעילו את הסקריפט באמצעות cron או מתזמן אחר הזמין בסביבה שלכם. למשל, אפשר להגדיר משימה שתריץ את קובץ Python פעם ביום ותעביר את המפתח ואת ביטויי החיפוש באמצעות משתני סביבה. לפני שימוש שוטף, בדקו בקשה אחת, אחר כך את הרשימה כולה, ורק אז הפעילו את לוח הזמנים.
כדי להבטיח הרצה אמינה, שמרו את הסטטוס של כל בקשה, הגבילו את מספר הניסיונות החוזרים במקרה של שגיאות זמניות, וסמנו איסוף חלקי אם ביטוי אחד נכשל. אל תכללו את המפתח בהודעות שגיאה. כדאי גם להפריד את הקבצים לפי תאריך ושם שאילתה, כדי שהרצה חוזרת לא תדרוס תמונת מצב קודמת.
בחרו את התדירות בהתאם למשימה ולהיקף הבקשות. לסקירה יומית מספיקה הרצה אחת ביום; איסוף תכוף יותר מתאים כשהצוות מעוניין בשינויים במהלך היום. התחילו ברשימה קטנה של ביטויים, בדקו את התועלת של התוצאות שהוחזרו, ואז הרחיבו את האיסוף בכפוף לתנאי הגישה ולכללי השימוש בנתונים.
השתמשו בבינה מלאכותית לקיבוץ לפי נושאים
לאחר אימות הסכמה של התגובה, אפשר להעביר למודל שדות טקסט נבחרים כדי לקבץ תיאורים לפי נושאים שהוגדרו מראש או להכין טיוטת סיכום קצרה. שמרו לצד הסיווג את מזהה הפרסום המקורי, את ביטוי החיפוש ואת קטע הטקסט שעליו מבוססת הקטגוריה. כך יוכל האנליסט לעבור מפלט המודל לרשומה המקורית.
חשבו הפרשים מספריים, מיינו והסירו כפילויות באמצעות קוד רגיל. מודל מתאים לעיבוד טקסט ולניסוח דוחות, ואילו את המונים ואת חותמות הזמן יש לקחת מהתגובות השמורות. הפרדה בין הפעולות מבהירה את מקורו של כל ממצא.
בדקו ידנית חלק מהקטגוריות האוטומטיות ושמרו תיקונים כדוגמאות בדיקה. אם סוגים שונים של פרסומים מתכנסים שוב ושוב לאותה קבוצה, חדדו את הגדרות הקטגוריות ובדקו מחדש. תהליך כזה מסייע להעריך את איכות הסיווג ביחס לנתונים של המשימה שלכם.
לסיכום: ארכיון שניתן לשחזור וסיכום שניתן לבדיקה
לאחר הפעלה של בקשה מתועדת עם הפרמטר keyword, עומד לרשות הצוות ארכיון שמראה אילו ביטויים הורצו, מתי, ואילו נתונים ה-API החזיר עבור כל אחד מהם. על בסיסו אפשר לבנות טבלת תוצאות, להשוות בין תמונות מצב שדות שאומתו, ולהכין רשימת פרסומים שנמצאו לצורך ניתוח ידני.
התחילו בבקשת בדיקה אחת, ואז הגדירו את רשימת הביטויים ואת לוח הזמנים. תיאור TikTok Scraper API מציג את כתובת הבסיס ואת מפת הנתיבים; הפרמטרים של /searchVideo ומבנה התגובה מתוארים ב-מפרט ה-API. ארכוב תגובות שאומתו יוצר בסיס לאנליטיקה שניתן לשחזר עבור ביטויי חיפוש קבועים.