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

במדריך הזה נגדיר איסוף כזה למקרה מסוים: צוות השיק תכונה חדשה ורוצה לעקוב מדי שבוע אחר סרטוני TikTok ציבוריים שתיאוריהם כוללים את שם המוצר, תכונת המפתח או בעיה אופיינית של משתמשים. זהו ניטור של מדגם תוצאות החיפוש: ה-API מחזיר תוצאות לפי השאילתה והפרמטרים, ולא רשימה מובטחת של כל הפרסומים על ההשקה.
ראשית, הגדירו איזה אות הצוות צריך
מספר צפיות גבוה כשלעצמו אינו מסביר היטב מה כדאי לעשות הלאה. לצוות מועיל יותר לדעת אילו שאלות חוזרות, אילו תרחישים אנשים מציגים ואילו סרטונים זוכים לתגובות ציבוריות בולטות. לכן, התחילו בניסוח של כמה שאילתות חיפוש ובהחלטה אילו שדות ייכללו בדוח.
לדוגמה, עבור השקת כלי לתכנון פרסומים אפשר לבדוק את השאילתות „שם המוצר”, „מתכנן תוכן” ו„איך לתזמן TikTok”. הביטויים צריכים לשקף דרכים שונות שבהן אנשים עשויים לתאר אותו נושא. תעדו אותם יחד עם תאריך תחילת הניטור והאזור, כדי שאפשר יהיה להשוות בין איסופים מאוחרים יותר תחת אותן הגדרות.
טבלה בסיסית יכולה לכלול את מועד האיסוף, שאילתת החיפוש, מזהה הסרטון, קישור, תיאור, שם היוצר, מזהה היוצר ואת ערכי הצפיות, הלייקים והתגובות הזמינים. TikTok Scraper API מתעד עבור תוצאות חיפוש שדות כגון aweme_id, desc, share_url, פרטי היוצר וחלק מהסטטיסטיקות. יש לבדוק כל שדה בכל אובייקט: מדדים מסוימים עשויים להיעדר.
השתמשו במסלול החיפוש המתועד
לחיפוש סרטונים השתמשו במסלול GET /searchVideo בכתובת הבסיס https://tiktok.evelode.com. התיעוד מפרט את הפרמטר הנדרש keyword ואת הפרמטרים האופציונליים count, cursor, date_posted, sort_by, region ו-cache_timeout. הערכים האפשריים לסינון לפי תאריך כוללים this-week, ואפשרויות המיון כוללות relevance, most-liked ו-date-posted. בדקו את מטרתם ושמותיהם במדריך מסלולי TikTok API.
מפתח הרישיון מועבר כפרמטר שאילתה license_key. בסקריפט עבודה קראו אותו ממשתנה הסביבה JSONSCRAPER_TIKTOK_LICENSE_KEY, אל תכתבו את הסוד בקוד המקור ואל תציגו אותו ביומנים. הדוגמה הזו מיועדת ל-Python 3.8 ומעלה ומשתמשת בחבילת requests:
import os
import requests
BASE_URL = "https://tiktok.evelode.com"
API_KEY = os.environ["JSONSCRAPER_TIKTOK_LICENSE_KEY"]
def search_videos(keyword, cursor=None):
params = {
"license_key": API_KEY,
"keyword": keyword,
"count": 20,
"date_posted": "this-week",
"sort_by": "date-posted",
"region": "US",
}
if cursor is not None:
params["cursor"] = cursor
response = requests.get(
f"{BASE_URL}/searchVideo",
params=params,
timeout=30,
)
response.raise_for_status()
payload = response.json()
if payload.get("status") != "ok":
raise RuntimeError("TikTok API החזיר סטטוס שאינו ok")
return payload["tiktok"]
result = search_videos("content planning app")
print("מספר האובייקטים שנמצאו:", len(result.get("aweme_list", [])))
הסקריפט בודק שגיאת HTTP ואת סטטוס התשובה החיצוני. תשובת HTTP מוצלחת אינה מבטיחה כשלעצמה שיש סרטונים בתוצאות החיפוש: מדגם ריק עשוי להחזיר רשימה ריקה. בהרצה הראשונה כדאי לשמור את התשובה המלאה באחסון מאובטח, כדי להשוות בין האובייקטים בפועל לבין טבלת השדות המנורמלים.
טפלו בשתי תבניות התשובה של החיפוש
לתוצאות החיפוש יש מאפיין מבני חשוב. הסרטונים עשויים להופיע ישירות בתוך tiktok.aweme_list, או בתוך tiktok.search_item_list[].aweme_info. אם המעבד קורא רק את הרשימה הראשונה, הוא עלול להחמיץ תוצאות שנמצאות בתבנית השנייה.
הוסיפו מנרמל קטן שתומך בשתי התבניות ומדלג בבטחה על פריטים שאין בהם אובייקט סרטון פנימי:
def extract_awemes(tiktok):
items = list(tiktok.get("aweme_list") or [])
for item in tiktok.get("search_item_list") or []:
aweme = item.get("aweme_info")
if aweme:
items.append(aweme)
return items
def normalize(aweme, keyword, collected_at):
author = aweme.get("author") or {}
stats = aweme.get("statistics") or {}
return {
"collected_at": collected_at,
"keyword": keyword,
"video_id": aweme.get("aweme_id"),
"posted_at": aweme.get("create_time"),
"description": aweme.get("desc"),
"share_url": aweme.get("share_url"),
"author_id": author.get("uid"),
"author_name": author.get("nickname"),
"views": stats.get("play_count"),
"likes": stats.get("digg_count"),
"comments": stats.get("comment_count"),
"shares": stats.get("share_count"),
}
ערך חסר נשאר None. אל תחליפו אותו באפס: אפס פירושו ערך שנמדד, ואילו None משמר את העובדה שהשדה לא הגיע. ההבדל הזה משפיע על ממוצעים, שיעורים וכל מסקנה שמסיקים לצוות.
שמרו היסטוריה, לא רק תמונת מצב עדכנית
כדי לראות מגמות, שמרו רשומות תצפית נפרדות. מזהה הסרטון מתאים למניעת כפילויות של פרסומים, אך לא למחיקת היסטוריה: הופעה חוזרת של אותו סרטון באיסוף הבא מספקת נקודת תצפית חדשה. למשל, אפשר ליצור מפתח ייחודי לטבלת התצפיות מ-video_id ומ-collected_at, ולשמור ברשומה גם את הקישור והתיאור כדי להקל על הבדיקה.
סכמה בסיסית ב-SQLite שימושית לאב-טיפוס:
import sqlite3
conn = sqlite3.connect("tiktok_observations.sqlite3")
conn.execute("""
CREATE TABLE IF NOT EXISTS observations (
video_id TEXT NOT NULL,
collected_at TEXT NOT NULL,
keyword TEXT NOT NULL,
posted_at INTEGER,
description TEXT,
share_url TEXT,
author_id TEXT,
author_name TEXT,
views INTEGER,
likes INTEGER,
comments INTEGER,
shares INTEGER,
PRIMARY KEY (video_id, collected_at, keyword)
)
""")
conn.commit()
בפועל, נרמלו את מועד האיסוף ל-UTC, שמרו את JSON המקורי בנפרד והוסיפו עמודה לגרסת הסכמה. התשובה המקורית עוזרת לאמת את ההמרה כאשר מבנה האובייקטים החדשים שונה מזה שהתרגלתם אליו. עבור פרסומים שנמצאו בכמה שאילתות, שמרו את מילות המפתח התואמות בטבלה מקושרת נפרדת או שלבו אותן בעת בניית הדוח.
עימוד: המשיכו רק באמצעות הסמן מהתשובה
הפרמטר cursor נועד להמשך החיפוש. לוקחים את ערכו מהתשובה הקודמת ומעבירים אותו בחזרה ללא שינוי; התהליך מסתיים כאשר has_more כבר לא מציין שיש תוצאות נוספות, או כשמגיעים למגבלה שהוגדרה. יש להתייחס לסמן כאטום: אל תחשבו אותו בעצמכם ואל תחליפו אותו במונה עמודים.
def collect_pages(keyword, max_pages=3):
cursor = None
collected = []
for _ in range(max_pages):
page = search_videos(keyword, cursor)
collected.extend(extract_awemes(page))
if not page.get("has_more"):
break
cursor = page.get("cursor")
if cursor is None:
break
return collected
הגבלת מספר העמודים הופכת את המשימה המתוזמנת לצפויה מבחינת מספר הבקשות. תעדו ביומן ההרצה את מספר העמודים ואת ערך has_more: כך יהיה לדוח הקשר לגבי המדגם. גם כשמשתמשים בעימוד, התוצאה מתארת את תשובות ה-API שהתקבלו ואת מגבלת האיסוף שהוגדרה; היא אינה אומדן של כלל הפרסומים בפלטפורמה.
בנו דוח שאפשר לחזור עליו
הפעילו את האיסוף לפי לוח זמנים, פעם בשבוע או בתדירות גבוהה יותר אם הצוות זקוק לאותות תכופים יותר. בכל הרצה תעדו את רשימת השאילתות, הפרמטרים, המועד, מספר האובייקטים שהתקבלו ומספר המזהים הייחודיים. ספרו בנפרד את הפרסומים שנצפו לראשונה בהרצה זו ואת אלה שכבר הופיעו בעבר.
הדוח יכול להציג ארבעה סוגי מידע פשוטים:
- סרטונים חדשים: קישורים, תיאורים, תאריך פרסום ושאילתת החיפוש שבאמצעותה הסרטון נמצא.
- נושאים חוזרים: קיבוץ תיאורים לפי קטגוריות שהוגדרו ידנית, למשל „שגיאת הגדרה”, „בקשת תכונה” ו„סקירת תרחיש”.
- תגובות ציבוריות: צפיות, לייקים, תגובות ושיתופים זמינים, לצד מועד התצפית.
- אותות לבדיקה: ניסוחים חדשים, שאלות נפוצות או סרטונים שכדאי לעובד או לעובדת לעיין בהם.
אל תכנו את ההפרש בין שתי תמונות מצב „לייקים חדשים” בלי לבדוק את המשמעות ואת העדכניות של הערכים בתשובה. ניסוח מדויק הוא „ערך המדד בתשובה האחרונה שהתקבלה” ו„ההפרש בין תמונות המצב שנשמרו”. כך הצוות רואה מה בדיוק חושב ויכול לפתוח את הפרסום המקורי לפני קבלת החלטה.
הוסיפו בינה מלאכותית לשלב הסיווג, לא במקום האיסוף
לאחר הנרמול אפשר להעביר תיאורי סרטונים למודל כדי לסווג אותם לפי קטגוריות שהוגדרו מראש. שלחו רק את שדות הטקסט הנחוצים ובקשו תוצאה מובנית: קטגוריה, נימוק קצר, רמת ביטחון וקטע מהתיאור שעליו מבוססת התווית. שמרו את הפרסום המקורי לצד התווית, כדי שאנליסט יוכל לבדוק מקרים שנויים במחלוקת.
תהליך העבודה נשאר פשוט: מתזמן מפעיל את האיסוף; Python בודק את התשובה ושומר את JSON; משימה נפרדת מנרמלת רשומות חדשות; מסווג מעבד רק תיאורים חדשים; והדוח נבנה מהמסד ונשלח לערוץ שהצוות בחר. TikTok Scraper API עצמו מספק נתוני חיפוש, ואילו הסיווג והעברת הדוח הם חלק מלוגיקת האינטגרציה שלכם, שאפשר לממש ב-Python, ב-n8n או ב-Make.
כדי להפחית רעש, הגדירו אוצר מילים לקטגוריות לפני שליחת הטקסט למודל ובדקו מעת לעת מדגם שתויג ידנית. לתיאורים קצרים או עמומים כדאי להוסיף סטטוס „אין מספיק הקשר” במקום לכפות בחירה בקטגוריה. תוויות שנוצרו באמצעות בינה מלאכותית עוזרות למיין את התור לבדיקה, אך יש לאמת מסקנות על בעיות משתמשים באמצעות קריאת הפרסומים והשוואה בין כמה תצפיות.
שגיאות, ניסיונות חוזרים וטיפול בטוח במפתח
בקשת רשת עלולה להסתיים בחריגה מפסק זמן, בשגיאה זמנית או בתשובה שלא ניתן לפענח כ-JSON. חלקו את הטיפול לשלבים: בקשה, בדיקת קוד HTTP, פענוח JSON, בדיקת הסטטוס החיצוני, נרמול ושמירה. במקרה של תקלות זמניות, השתמשו במספר מוגבל של ניסיונות חוזרים עם השהיה הולכת וגדלה; תעדו שגיאות קבועות לצורך בדיקה מאוחרת יותר ואל תסמנו את ההרצה כהצלחה.
שמרו את המפתח במנהל סודות של סביבת ההרצה או במשתנה סביבה. מכיוון שה-API מקבל את license_key כחלק ממחרוזת השאילתה, הימנעו מתיעוד כתובת ה-URL המלאה ופרמטרי הבקשה: הם יחשפו את הסוד. לצורכי אבחון תעדו את המסלול, קוד התשובה, משך הזמן, שאילתת החיפוש ומזהה המשימה, תוך הסרת המפתח מהיומנים.
קבעו את לוח הזמנים ואת היקף המדגם בהתאם למשימה שלכם ולתנאי השימוש בפלטפורמה. כדאי להגביל את איסוף הנתונים הציבוריים למה שנחוץ באמת לניתוח; את אחסון התיאורים, הקישורים ומזהי היוצרים יש להסדיר בכללים הפנימיים של הצוות. תשובות API ומדדים עשויים להיות חלקיים או להשתנות בין תצפיות, לכן הדוח צריך לשמור את מועד האיסוף ואת מקורו של כל פריט.
התוצאה: מקישורים ידניים להיסטוריה שאפשר לאמת
לאחר ההגדרה, הצוות מקבל רשימה שמתעדכנת בקביעות של סרטונים שנמצאו, תשובות מקוריות לצורכי ביקורת, טבלה של מדדים ציבוריים זמינים וסקירה של נושאים חוזרים. כך אפשר לזהות מהר יותר שאלות על תכונה חדשה, למצוא דוגמאות לתרחישי שימוש ולבחור פרסומים לניתוח ידני. השוואת תמונות מצב מראה איך משתנים הערכים שנשמרו עבור סרטונים שכבר נמצאו, ויומן השאילתות מסביר כיצד נוצר המדגם.
התחילו בשאילתה אחת ובמגבלת עמודים נמוכה, בדקו את מבנה התשובה בפועל, ואז הוסיפו ניסוחים נוספים ולוח זמנים. לפני העברת אב-הטיפוס לסביבת ייצור, הגדירו כללים למניעת כפילויות, לשמירה ולטיפול בשגיאות. אפשר למצוא מסלולים ופרמטרים עדכניים בתיעוד הרשמי של ה-API; תיאור היכולות ואפשרות להתחיל לבדוק זמינים בדף TikTok Scraper API.