Контент-команда помічає нову тему в TikTok, коли про неї вже говорять конкуренти. Причина часто проста: пошук перевіряють вручну й нерегулярно, а знайдені посилання залишаються в чаті без спільної таблиці, дати збору та зіставних показників. Щоб помічати зміни раніше, корисно перетворити пошук на повторюваний процес: фіксувати запити, регулярно зберігати знайдені відео й порівнювати лише результати, за якими справді спостерігали.
Нижче наведено схему такого моніторингу на Python із TikTok Scraper API jsonscraper. Вона підійде, наприклад, агентству, яке відстежує кілька тематичних запитів для календаря публікацій, або бренду, якому важливо побачити, які публічні ролики на певну тему отримують помітну кількість переглядів і реакцій. API повертає результати пошуку TikTok, зокрема опис ролика, автора, дату публікації, посилання та доступні лічильники. Скрипт архівує кожну відповідь і формує CSV-знімок для аналізу.
Ключовий принцип — рахувати не абстрактний «тренд», а зміни у власному журналі спостережень: які ролики з’явилися у вибірці, які вже відомі відео змінили публічні лічильники, які формулювання повторюються в описах. Такий підхід дає контент-команді перевірювану чергу тем для ручної оцінки та зберігає походження кожного висновку.
Чому ручний пошук перетворюється на слабкий моніторинг
Пошукова видача — це вибірка, яка змінюється, а не стабільний каталог публікацій. Якщо сьогодні працівник знаходить десять роликів за словом, а наступного тижня знову відкриває пошук, порівняти результати складно: попередні посилання могли загубитися, набір результатів буде іншим, а лічильники встигнуть змінитися. Без збережених знімків неможливо відновити, що саме команда бачила певного дня.
Навіть простий щоденний збір усуває частину цієї проблеми. Для кожного запуску зберігаються дата спостереження, пошуковий термін, ідентифікатор ролика, автор, опис, посилання та доступні показники. Під час наступного запуску можна зіставити записи за ID відео й обчислити різницю між значеннями лічильників, якщо обидві версії містять відповідні поля.
Ці значення слід трактувати як публічні метрики роликів, помічених у відповіді API, а не як повне охоплення TikTok або вичерпний рейтинг популярності. Результати пошуку можуть змінюватися, окремі поля можуть бути відсутні, а показники залежать від часу збору. Тому мета пайплайна — сформувати відтворювану робочу вибірку й виявити кандидатів для перевірки, а не оголошувати тему універсальним трендом на підставі одного числа.
Схема рішення: пошук, архів, порівняння
Пайплайн складається з п’яти частин: конфігурації ключових слів, запиту до API, незміненого архіву JSON, нормалізованого шару записів і звіту про зміни. Такий поділ дає змогу окремо перевірити роботу кожного кроку. Якщо схема відповіді зміниться або окремі поля будуть відсутні, вихідний JSON залишиться доступним для повторної обробки.
- Визначте набір запитів. Використовуйте конкретні фрази, пов’язані з продуктом, галуззю або завданням аудиторії. Наприклад, бренд кухонної техніки може відстежувати «meal prep», «air fryer recipes» і назву конкретної категорії продукту. Зберігайте список запитів у конфігураційному файлі, а не вбудовуйте його в логіку обробки.
- Задайте правила збору. Виберіть розклад і невеликий обсяг результатів для пілоту. Записуйте дату, регіон і параметри пошуку. Для порівняння в часі важливіше повторювати налаштування, ніж намагатися отримати якомога ширшу відповідь за один запуск.
- Зберігайте вихідну відповідь. Записуйте JSON разом із часом запуску та пошуковим словом. Архів допомагає відновити вихідний запис і виправити нормалізацію без повторного виклику API.
- Нормалізуйте підтверджені поля. Витягуйте лише поля, які є у відповіді: ID, підпис, час публікації, автора, посилання й доступні значення статистики. Відсутнє значення залишайте порожнім, не замінюючи його нулем.
- Порівнюйте знімки. Зіставляйте ролики за ID і зберігайте кожне спостереження окремо. Після цього можна визначати нові для архіву публікації та різницю між спостережуваними значеннями метрик.
Для початкового тестування виберіть два-три запити й невелику кількість результатів. Перевірте, наскільки описи й автори відповідають вашому завданню, які поля фактично повертаються та наскільки повторюється вибірка за однакових умов. Лише після цього має сенс розширювати список термінів і переходити до запуску за розкладом.
Що саме можна запитати через TikTok Scraper API
В офіційній документації jsonscraper маршрут GET /searchVideo призначений для пошуку відео за ключовим словом. Обов’язковий параметр — keyword. Серед задокументованих необов’язкових параметрів — count, cursor, date_posted, sort_by, region і cache_timeout. У документації для date_posted наведено такі значення, як this-week і this-month, а для sort_by — relevance, most-liked і date-posted. Точні назви й призначення параметрів наведено в довіднику маршрутів TikTok API.
Базова адреса сервісу — https://tiktok.evelode.com; ключ передається як query-параметр license_key. У прикладі нижче ключ зберігається в змінній середовища JSONSCRAPER_TIKTOK_LICENSE_KEY. Це дає змогу не вбудовувати секрет безпосередньо у вихідний код і не виводити його в журнал виконання.
Відповідь потрібно розбирати з урахуванням вкладеної структури. Спочатку перевірте зовнішній status, а потім переходьте до об’єкта tiktok. Для пошуку можливі дві форми списку: ролики можуть міститися безпосередньо в tiktok.aweme_list, а також в елементах tiktok.search_item_list усередині aweme_info. Водночас aweme_list у відповіді пошуку може бути порожнім, хоча ролики є в search_item_list. Скрипт нижче підтримує обидві форми.
У документації та перевіреному прикладі відповіді для об’єкта ролика наведено такі поля, як aweme_id, desc, create_time, share_url, відомості про автора й об’єкт statistics. Статистика може містити лічильники переглядів, уподобань, коментарів і репостів. Конкретний набір і значення полів потрібно перевіряти в кожній відповіді: код залишає відсутні поля порожніми. Приклад маршруту та його задокументовані параметри доступні в описі TikTok Scraper API.
Робочий приклад на Python
Приклад призначений для Python 3.8 і новіших версій та використовує пакет requests. Установіть його командою python -m pip install requests. Збережіть код у файлі collect_tiktok.py, задайте ключ у середовищі й запустіть скрипт із пошуковим словом. Скрипт створює каталог data, записує вихідний JSON і додає нормалізовані спостереження до CSV.
import csv
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
from urllib.parse import urlparse
import requests
BASE_URL = "https://tiktok.evelode.com"
ARCHIVE = Path("data/raw")
OUT_CSV = Path("data/observations.csv")
def get_videos(tiktok):
"""Зібрати ролики з підтверджених варіантів відповіді searchVideo."""
videos = []
aweme_list = tiktok.get("aweme_list") or []
if isinstance(aweme_list, list):
videos.extend(item for item in aweme_list if isinstance(item, dict))
search_items = tiktok.get("search_item_list") or []
if isinstance(search_items, list):
for item in search_items:
if not isinstance(item, dict):
continue
aweme_info = item.get("aweme_info")
if isinstance(aweme_info, dict):
videos.append(aweme_info)
# Видаляємо дублікати, зберігаючи порядок і записи без ID.
result = []
seen = set()
for video in videos:
video_id = video.get("aweme_id")
if video_id and video_id in seen:
continue
if video_id:
seen.add(video_id)
result.append(video)
return result
def fetch(keyword, count=20, region="US"):
license_key = os.environ.get("JSONSCRAPER_TIKTOK_LICENSE_KEY")
if not license_key:
raise RuntimeError("Set JSONSCRAPER_TIKTOK_LICENSE_KEY in the environment")
params = {
"license_key": license_key,
"keyword": keyword,
"count": count,
"region": region,
"sort_by": "relevance",
}
response = requests.get(
f"{BASE_URL}/searchVideo", params=params, timeout=60
)
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")
if not isinstance(tiktok, dict):
raise RuntimeError("Response does not contain a TikTok result object")
return payload, tiktok
def write_rows(keyword, videos, collected_at):
OUT_CSV.parent.mkdir(parents=True, exist_ok=True)
fields = [
"collected_at", "keyword", "aweme_id", "create_time",
"author_id", "author_name", "author_username", "description",
"share_url", "play_count", "digg_count", "comment_count",
"share_count", "collect_count",
]
write_header = not OUT_CSV.exists()
with OUT_CSV.open("a", newline="", encoding="utf-8") as file:
writer = csv.DictWriter(file, fieldnames=fields)
if write_header:
writer.writeheader()
for video in videos:
author = video.get("author") or {}
stats = video.get("statistics") or {}
writer.writerow({
"collected_at": collected_at,
"keyword": keyword,
"aweme_id": video.get("aweme_id"),
"create_time": video.get("create_time"),
"author_id": author.get("uid"),
"author_name": author.get("nickname"),
"author_username": author.get("unique_id"),
"description": video.get("desc"),
"share_url": video.get("share_url"),
"play_count": stats.get("play_count"),
"digg_count": stats.get("digg_count"),
"comment_count": stats.get("comment_count"),
"share_count": stats.get("share_count"),
"collect_count": stats.get("collect_count"),
})
def main():
if len(sys.argv)
Передайте ключ через середовище. У shell Bash команда для поточного сеансу виглядає так:
export JSONSCRAPER_TIKTOK_LICENSE_KEY="ваш_ключ"
python collect_tiktok.py "meal prep"
У Windows PowerShell змінну можна задати для поточного процесу командою $env:JSONSCRAPER_TIKTOK_LICENSE_KEY="ваш_ключ", а потім запустити той самий файл Python. Не додавайте ключ до репозиторію, CSV, архіву відповіді чи повідомлень про помилки. Оскільки API приймає ключ у query-параметрі, враховуйте, що повна URL-адреса запиту може потрапляти до журналів HTTP-клієнта й інфраструктури; налаштуйте логування так, щоб секрети не записувалися.
Як читати код і перевіряти результат
Функція fetch передає задокументовані параметри й перевіряє HTTP-код, зовнішній статус і наявність об’єкта tiktok. Вона не вважає будь-яке коректне тіло відповіді успішним результатом: якщо формат несподіваний, виконання зупиняється з зрозумілою помилкою. Так легше відрізнити порожню видачу від проблеми з доступом або зміненої структури.
Функція get_videos об’єднує елементи прямого списку aweme_list і записи, вкладені в search_item_list[].aweme_info. Потім вона видаляє повтори за aweme_id, оскільки ролик може з’явитися в обох колекціях. Якщо ID відсутній, запис зберігається; це дає змогу дослідити вихідний результат, не підставляючи вигадане значення.
Нормалізація використовує безпечне отримання вкладених об’єктів. Поля автора або статистики можуть бути відсутні, тому перед читанням код підставляє порожній об’єкт. Відповідні клітинки CSV залишаються порожніми. Це важлива відмінність: порожня клітинка означає, що значення не надійшло в спостереженні, а нуль — числове значення, яке API справді повернув.
Для кожного запиту архів створює окремий JSON-файл. Ім’я містить час UTC і очищену версію пошукового слова. CSV зберігає плоскі записи для аналітики, а вихідний JSON залишається еталонним матеріалом для розбору нових полів або повторної обробки. Такий подвійний формат зручний і для локального прототипу, і для подальшої міграції до бази даних або об’єктного сховища.
Щоб перевірити перший запуск, відкрийте JSON і переконайтеся, що status дорівнює ok, усередині є об’єкт tiktok, а одна або обидві підтримувані колекції містять елементи. Потім зіставте кілька значень CSV із вихідним об’єктом. Зокрема, перевірте, що лічильники не перетворюються на рядки з помилками, дати публікацій зберігаються у вихідному вигляді, а посилання відповідають тим самим роликам, що й ID.
Якщо коректна відповідь не містить роликів, збережіть цей факт як порожній результат запуску, а не як збій коду. Якщо зовнішній статус або HTTP-відповідь указує на помилку, не додавайте такий запис до аналітичних спостережень: спочатку усуньте причину й повторіть запуск. Для виробничого процесу також варто записувати HTTP-код, пошукове слово, час і коротке повідомлення про помилку, не зберігаючи ключ і повну URL-адресу із секретом.
Пагінація та повторюваність збору
Пошук підтримує параметр cursor для прокручування результатів. Щоб отримати наступну сторінку, візьміть курсор із попередньої відповіді й передайте його без перетворень. Курсор — непрозоре значення API: застосунок має зберігати й повертати його як є, не обчислювати за кількістю рядків і не трактувати як номер сторінки.
Для початкового моніторингу можна обмежитися одним запитом на ключове слово й однаковим count. Це простіше для інтерпретації: команда розуміє, що кожен запуск зберігає обмежений знімок видачі. Якщо додаєте пагінацію, зберігайте кожну сторінку та курсор, а також задайте обмеження на кількість сторінок за один запуск. Це обмеження захистить завдання від нескінченного циклу в разі неочікуваної відповіді.
Параметр date_posted дає змогу обмежити пошук одним із періодів, перелічених у документації; sort_by дає змогу вибрати сортування за релевантністю, датою публікації або вподобаннями. Під час аналізу динаміки фіксуйте ці налаштування разом із даними запуску. Порівняння запитів із різними періодами чи способами сортування може відображати зміну умов пошуку, а не зміну самої теми.
Параметр cache_timeout керує кешуванням відповіді. У документації зазначено стандартне вікно кешу в 3600 секунд і значення 0 для вимкнення кешування. Для планового моніторингу виберіть налаштування свідомо й збережіть їх у конфігурації. Якщо серію запитів запускають частіше ніж раз на годину й потрібно розрізняти відповіді в межах цього вікна, окремо перевірте поведінку кешування, перш ніж трактувати повторювані результати як відсутність змін.
Порівняння щоденних спостережень
CSV уже містить основу для простого звіту. Групуйте рядки за пошуковим словом і aweme_id, сортуйте за collected_at і порівнюйте лише пари спостережень, у яких є обидва значення метрики. Наприклад, різницю переглядів можна обчислити як останнє спостережуване значення мінус попереднє. Зберігайте обидві вихідні точки: абсолютна різниця й час між спостереженнями потрібні, щоб правильно зрозуміти результат.
Не називайте цю різницю швидкістю переглядів, якщо часовий інтервал не визначено. Якщо один запуск відбувся вранці, а наступний — через кілька днів, значення відображає накопичену зміну за цей проміжок. Для зіставного темпу можна поділити різницю на фактичний час між спостереженнями, але результат однаково буде середнім темпом між двома знімками, а не безперервною телеметрією.
Окремо рахуйте два типи сигналів. Перший — нові ID, які з’явилися у видачі за поточним запитом. Другий — зміна статистики вже спостережуваних відео. Новий ролик може бути кандидатом для перевірки незалежно від поточної кількості переглядів, а зростання показників старого відео допомагає помітити, що публікація й далі набирає реакції. Ці сигнали відповідають на різні запитання й корисні для різних сценаріїв редакційного планування.
Додайте прості перевірки якості даних: частку рядків з ID, частку рядків з описом, наявність дати збору, кількість унікальних роликів на запит і число відсутніх значень статистики. Такі показники допомагають вчасно побачити, що пайплайн перестав отримувати звичну структуру, — до того, як команда зробить висновок на підставі неповного файла. Вони також показують, які пошукові фрази дають корисну для вашої галузі вибірку.
Для першого звіту достатньо таблиці з колонками: термін, ID, дата публікації, автор, опис, посилання, поточні перегляди, перегляди в попередньому знімку, різниця й час між знімками. Додайте прапорець «нове в архіві» та поле для редакційної оцінки. Працівник може відзначати відповідність бренду, придатність формату й потенційний ризик копіювання чужої ідеї — API самостійно таких оцінок не робить.
Як не сплутати популярність ролика з корисністю теми
Перегляди, уподобання, коментарі й репости допомагають описати публічну реакцію на конкретний ролик. Для контент-планування важливий також сам текст: формулювання запитання, обіцянка на початку, повторюваний формат пояснення або тип демонстрації. Тому передавайте редактору посилання й опис разом із метриками; одне число рідко пояснює, чому публікація спрацювала.
Порівнюючи кілька відео, можна обчислити співвідношення взаємодій до переглядів, якщо наявні обидва лічильники. Наприклад, сума вподобань, коментарів і репостів, поділена на кількість переглядів, дає простий показник спостережуваної частки реакцій. Зафіксуйте формулу й не змішуйте ролики з пропущеними значеннями: інакше результат буде непорівнянним. Цей коефіцієнт описує лише вибрані публічні лічильники та відео.
Не підсумовуйте метрики кількох знімків так, ніби це незалежні події. Якщо той самий ролик потрапив у п’ять щоденних відповідей, його перегляди в цих рядках — послідовні стани одного лічильника, а не п’ять різних аудиторій. Щоб підсумувати унікальні публікації, використовуйте одну узгоджену точку спостереження для кожного ролика, наприклад останній знімок за звітний період, і зафіксуйте правило вибору.
Ще один корисний зріз — слова, що повторюються в описах. Простий текстовий аналіз може групувати публікації за заздалегідь визначеними словниками: «рецепт», «огляд», «до/після», «помилка», «порада». Класифікатор або мовна модель можуть пропонувати категорії та короткі резюме, однак у таблиці варто зберігати оригінальний опис і URL, щоб редактор міг перевірити інтерпретацію за самим роликом.
Автоматизація за розкладом
Після перевірки ручного запуску перенесіть збір до планувальника: cron на власному сервері, GitHub Actions або робочий процес n8n/Make. Інтеграція має запускати той самий перевірений скрипт, передавати ключ зі сховища секретів, архівувати JSON і надсилати сповіщення лише в разі успішного завершення. Конкретна реалізація планувальника залежить від інфраструктури; виклик API й формат обробки залишаються незмінними.
Приклад розкладу cron для щоденного запуску о 08:15 за часом машини:
15 8 * * * cd /srv/tiktok-monitor && /usr/bin/python3 collect_tiktok.py "meal prep" >> logs/collector.log 2>&1
Перш ніж використовувати цей рядок, налаштуйте змінну середовища в службі або оболонці, під якою працює cron, і задайте правильний часовий пояс хоста. Для кількох ключових слів краще зберігати список у файлі, а скрипту передавати кожен запит окремим запуском. Так помилка одного запиту не обов’язково скасовуватиме весь набір, а архіви буде легше зіставляти.
Коли кількість ключових слів зросте, винесіть конфігурацію в JSON або YAML і додайте журнал запусків зі статусом, кількістю отриманих роликів і шляхом до архіву. Для надійності передбачте обмежену кількість повторів у разі тимчасової мережевої помилки, тайм-аут і окрему обробку HTTP-помилок. Не можна повторювати запити нескінченно: завдання має завершуватися з помітним статусом, щоб наступний запуск не приховував проблему.
Якщо результати мають надходити до Google Sheets, бази даних або внутрішньої панелі, додайте це після надійного архівування. Спочатку запишіть вихідну відповідь, а потім завантажуйте нормалізовані рядки; якщо передавання не вдалося, повторіть його з архіву, не обов’язково збираючи дані заново. Ідентифікатор ролика й час збору допомагають організувати повторюване вставлення та відрізнити новий знімок від старого.
Додавання ШІ: корисна роль — сортування, а не підміна джерела
Коли в архіві накопичиться багато описів, модель може допомогти згрупувати відео за темами, виокремити формулювання, що часто трапляються, і підготувати короткі пояснення для редактора. Передавайте моделі обмежений набір полів: пошукове слово, опис, дату публікації та публічні лічильники. Просіть повертати структуровані категорії й коротке обґрунтування, а не впевнені твердження про причини популярності, яких у даних немає.
Зберігайте результат роботи моделі в окремих колонках, наприклад ai_topic, summary і review_status. Не перезаписуйте вихідний опис і значення API. У разі зміни інструкції чи моделі повторну обробку потрібно мати змогу виконати на збережених записах; для цього корисно зберігати версію промпту й дату класифікації.
Практичне завдання для моделі — запропонувати редактору кластери: «короткі рецепти», «порівняння пристроїв», «помилки початківців». Потім аналітик перевіряє за посиланнями кілька прикладів у кожному кластері й коригує словник. Такий процес із залученням людини перетворює ШІ на засіб навігації корпусом, водночас залишаючи доступними перевірювані вихідні спостереження.
Не доручайте моделі самостійно встановлювати причинно-наслідковий зв’язок між форматом і охопленням на підставі невеликої пошукової вибірки. Для такого висновку потрібні заздалегідь визначена методика, зіставні публікації й додаткові дані. У практичній редакційній роботі достатньо ранжування кандидатів для перегляду, гіпотез про повторювані сюжети та списку посилань для ручного аналізу.
Якість вибірки та межі висновків
Пайплайн зберігає відповіді, отримані за заданими запитами й параметрами. Він допомагає порівнювати ці спостереження, однак охоплення пошуку обмежене конкретним запитом, часом збору, налаштуваннями та відповіддю сервісу. Тому формулюйте висновки точно: «серед отриманих результатів за запитом X у знімках цього тижня частіше траплялася тема Y», а не «TikTok зараз повністю обговорює Y».
Порівнюйте лише однаково налаштовані серії: той самий регіон, однакові параметри сортування, період публікації та кількість запитаних результатів. Якщо змінюєте запит або фільтр, позначте це як нову серію. Для аналізу сезонності чи кампанії корисно зберігати версію конфігурації, інакше зміна вхідних даних виглядатиме як зміна контенту.
Публічні метрики можуть оновлюватися між знімками й мати різний вік: нещодавно опублікований ролик і старий ролик перебувають на різних етапах накопичення реакцій. Порівнюючи ефективність, враховуйте дату публікації та інтервал спостереження. Зіставляйте публікації схожого віку або аналізуйте динаміку того самого ID у послідовних знімках.
Якщо проєкт пов’язаний із конкурентами або авторами, обмежте збір поставленим завданням і мінімально необхідними даними. Не збирайте чутливу інформацію й не використовуйте публічні показники для оцінювання особистості автора. Для звіту маркетинговій команді зазвичай достатньо посилання, опису, імені профілю, часу публікації та агрегованих метрик. Перед автоматизацією перевірте застосовні умови платформи, вимоги вашої організації та правила зберігання даних.
Практичний чекліст перед запуском
- Сформулюйте бізнес-запитання: які теми, формати або публікації потрібно помічати.
- Почніть із кількох стабільних пошукових фраз і зафіксуйте їх написання.
- Перевірте маршрут
/searchVideo, обов’язковий параметрkeywordта решту параметрів за документацією. - Зберігайте ключ у змінній середовища й не допускайте його появи у виводі, журналах і репозиторії.
- Перевіряйте зовнішній статус відповіді та наявність об’єкта
tiktok. - Обробляйте і
aweme_list, іsearch_item_list[].aweme_info. - Зберігайте вихідний JSON до нормалізації.
- Залишайте відсутні поля порожніми й не підміняйте їх нулями.
- Зіставляйте публікації за
aweme_id, а курсор передавайте без перетворень. - Фіксуйте дату збору й параметри пошуку для кожного знімка.
- Перевіряйте кілька роликів вручну, перш ніж робити висновки й передавати результати моделі.
Що буде на виході
Після налаштування команда матиме повторюваний процес: список ключових запитів запускатиметься за розкладом, кожна відповідь зберігатиметься як вихідний JSON, а нормалізовані спостереження додаватимуться до CSV. Аналітик зможе побачити нові для архіву відео, повернутися до посилань та описів, порівняти доступні публічні лічильники за знімками й сформувати тематичні групи.
Результатом для редактора буде не автоматичний вердикт про «головний тренд», а короткий список кандидатів, які можна перевірити: нові публікації, ролики з помітною зміною показників і повторювані сюжетні формулювання. Це скорочує шлях від ручного пошуку до обговорення теми й залишає перевірювану основу для рішення про те, що варто включити до контент-плану.
Почати можна з одного запиту, щоденного локального запуску й CSV-файла. Коли перевірка покаже, що вибірка відповідає завданню, додайте розклад, базу даних або класифікацію описів. Задокументовані параметри й призначення маршрутів можна звірити в документації TikTok API, а відомості про доступ і продукт — на сторінці TikTok Scraper API jsonscraper.