Säljteam får samma fråga från olika kanaler: vilka uppgifter försöker potentiella kunder redan lösa? Manuella sökningar på TikTok ger en brokig samling videor, men det är svårt att upprepa sökningen en vecka senare, jämföra resultaten och förklara varför en viss video hamnade i rapporten. För en mindre undersökning kan offentliga sökresultat för några precisa sökfraser omvandlas till ett reproducerbart dataflöde: spara råsvaret, plocka ut fält om videon och skaparen, ta bort dubbletter och bedöm separat tecken på köp- eller produktvalsintresse.

Nedan visas ett fungerande upplägg i Python med TikTok Scraper API från jsonscraper. Det kan exempelvis passa en tjänst för videoredigering som vill se hur kreatörer beskriver problem med undertexter, mallar och export. Skriptet samlar in returnerade sökresultat, och en analytiker granskar sedan klassificeringen och avgör vilka formuleringar som bör användas i en målgruppsundersökning. Det här är ett sätt att organisera observationer av offentligt innehåll, inte en automatisk räkning av alla användare med köpintention.
Problemet: målgruppens sökfraser finns, men undersökningen är svår att upprepa
Manuell research tappar lätt sammanhang. En medarbetare söker efter ”hur man lägger till undertexter”, en annan efter ”automatiska undertexter för Reels”, och en tredje sparar bara videor som hen gillar. Slutresultatet blir en tabell där olika sökfraser, datum, mätvärden och urvalskriterier blandas. När en chef ber teamet upprepa analysen eller jämföra två veckor måste man återskapa både resultaten och själva sökprocessen.
Det är bättre att i förväg definiera observationsenheten: en hittad video med beskrivningstext, identifierare, länk, skapare och tillgängliga offentliga mätvärden. För varje video sparas den ursprungliga sökfrasen och tidpunkten för insamlingen. Då går det att besvara frågor separat: vilka formuleringar förekommer, vilka problem nämns, vilka videor har fått fler offentliga reaktioner och vad har förändrats mellan sparade ögonblicksbilder.
Som exempel tar vi ett företag som utvecklar ett verktyg för att skapa undertexter och korta videor. Företaget vill hitta offentliga videor där kreatörer uttryckligen diskuterar manuell transkribering, fel i taligenkänning, textningens timing eller innehåll som ska publiceras på flera plattformar. Man bör inte tillskriva kreatören etiketter som ”lead” eller ”köpare” utifrån en enda video. En analytiker kan rangordna innehållet efter observerbara tecken och därefter granska slutsatserna manuellt.
Lösningens upplägg: sökning, registrering, rensning och bedömning
Pipelinen består av fyra steg. Först tar teamet fram en liten ordlista med sökfraser, där varje fras motsvarar en konkret målgruppsuppgift. Därefter söker skriptet efter videor och sparar hela JSON-svaret. I det tredje steget normaliseras olika svarstrukturer till en gemensam rad per video och dubbletter tas bort med hjälp av identifieraren. Slutligen tilldelar regler eller en separat AI-klassificerare en prioritet för manuell granskning, samtidigt som skälet till bedömningen sparas.
Att separera stegen är viktigt för reproducerbarheten. Råsvaret hjälper till att undersöka förändringar i fält eller fel i normaliseringen. Den normaliserade tabellen är praktisk för filtrering och visualisering. En separat bedömningstabell gör det möjligt att ändra regler utan att anropa API:t på nytt, om de sparade uppgifterna lämpar sig för ny bearbetning och följer teamets lagringsperiod.
Som grundläggande sökfraser kan man använda ”fel i automatiska undertexter”, ”hur lägger man snabbt till undertexter” och ”redigera korta videor för företag”. Det här är bara exempel på sökord; formuleringarna bör anpassas till målgruppens språk och produkten. Spara sökfraserna tillsammans med resultaten, eftersom olika ord ger olika urval.
Vad TikTok Scraper API tillhandahåller
I jsonscrapers publicerade dokumentation anges GET-rutten /searchVideo på basadressen https://tiktok.evelode.com för videosökning. Den obligatoriska parametern är keyword; dokumenterade tilläggsparametrar omfattar count, cursor, region, date_posted, sort_by och cache_timeout. Exempelvis stöder sort_by de dokumenterade värdena most-liked, relevance och date-posted, medan date_posted kan ha värden som this-week eller all-time. Den exakta parameterlistan och beskrivningen av rutten finns i referensen för TikTok API:s ändpunkter.
Nyckeln skickas som frågeparameter med namnet license_key. I exemplet nedan läses den från miljövariabeln JSONSCRAPER_TIKTOK_LICENSE_KEY, så att hemligheten inte lagras i koden eller skrivs ut i loggen. Följ de aktuella villkoren för din åtkomst när du autentiserar dig och väljer parametrar. På sidan för TikTok Scraper API finns en produktbeskrivning och länkar till demo och dokumentation.
Sökresultatet måste läsas utifrån sin struktur, inte utifrån antagandet att det alltid innehåller en enda array. I ett verifierat exempel returnerade API:t en övergripande status och ett tiktok-objekt. Videor kan finnas i tiktok.aweme_list, och för sökresultat förekommer även tiktok.search_item_list[].aweme_info. Kontrollera båda formerna. Om ett fält finns kan de hittade objekten innehålla video-ID, beskrivning, länk, publiceringstid, uppgifter om skaparen och statistik, till exempel visningar, gilla-markeringar, kommentarer och delningar. Mätvärden och fält ska betraktas som valfria: koden ska inte fylla i påhittade nollor när ett värde saknas.
Sökningens paginering använder cursor. Om skriptet fortsätter hämtningen ska det skicka det mottagna värdet vidare som en ogenomskinlig token för nästa anrop, inte räkna ut token själv. För en första prototyp är det rimligt att begränsa insamlingen till en sida per sökfras. Det förenklar granskningen och ger en förutsägbar belastning. Därefter kan paginering läggas till med en gräns för antal sidor och skydd mot upprepade markörer.
Förbereda miljön
Exemplet använder Python 3.8 eller senare och standardbiblioteket. Ange nyckeln i miljön, till exempel i ett macOS- eller Linux-skal:
export JSONSCRAPER_TIKTOK_LICENSE_KEY="din_nyckel"
python tiktok_demand.py
I Windows PowerShell kan du ange miljövariabeln så här:
$env:JSONSCRAPER_TIKTOK_LICENSE_KEY="din_nyckel"
python .\tiktok_demand.py
Skriptet gör ett separat anrop för varje sökord. Det kontrollerar HTTP-fel, JSON-svaret och den övergripande statusen, och hämtar sedan objekt från båda bekräftade arrayvarianterna. Råsvaret skrivs rad för rad till en JSONL-fil: varje post innehåller sökfrasen, observationstidpunkten och råsvaret. Den andra delen skapar en CSV-fil med enhetliga fält. Nyckeln lagras inte i koden och hemligheten skrivs inte ut.
Exempel: samla in och normalisera sökresultat
import csv
import json
import os
import time
from datetime import datetime, timezone
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen
BASE_URL = "https://tiktok.evelode.com/searchVideo"
QUERIES = [
"fel i automatiska undertexter",
"hur lägger man snabbt till undertexter",
"redigera korta videor för företag",
]
def extract_videos(payload):
"""Stöder båda observerade strukturerna för söksvar."""
tiktok = payload.get("tiktok") or {}
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
video = item.get("aweme_info")
if isinstance(video, dict):
videos.append(video)
return videos
def fetch(query, license_key):
params = {
"keyword": query,
"count": 20,
"sort_by": "relevance",
"date_posted": "this-month",
"region": "US",
"license_key": license_key,
}
url = BASE_URL + "?" + urlencode(params)
request = Request(url, headers={"Accept": "application/json"})
try:
with urlopen(request, timeout=45) as response:
payload = json.loads(response.read().decode("utf-8"))
except HTTPError as exc:
raise RuntimeError("API returned HTTP status {}".format(exc.code)) from exc
except (URLError, TimeoutError, json.JSONDecodeError) as exc:
raise RuntimeError("Could not complete or parse API request") from exc
if payload.get("status") != "ok":
raise RuntimeError("API response status was not ok")
return payload
def metric(statistics, key):
value = statistics.get(key)
return value if isinstance(value, (int, float)) else ""
def main():
license_key = os.environ.get("JSONSCRAPER_TIKTOK_LICENSE_KEY")
if not license_key:
raise SystemExit("Set JSONSCRAPER_TIKTOK_LICENSE_KEY in the environment")
raw_path = Path("tiktok_raw.jsonl")
csv_path = Path("tiktok_videos.csv")
seen_ids = set()
rows = []
with raw_path.open("a", encoding="utf-8") as raw_file:
for query in QUERIES:
observed_at = datetime.now(timezone.utc).isoformat()
payload = fetch(query, license_key)
raw_file.write(json.dumps({
"query": query,
"observed_at": observed_at,
"response": payload,
}, ensure_ascii=False) + "\n")
for video in extract_videos(payload):
video_id = video.get("aweme_id")
if not video_id or video_id in seen_ids:
continue
seen_ids.add(video_id)
author = video.get("author") or {}
stats = video.get("statistics") or {}
rows.append({
"query": query,
"observed_at": observed_at,
"video_id": video_id,
"created_at": video.get("create_time", ""),
"description": video.get("desc", ""),
"share_url": video.get("share_url", ""),
"author_username": author.get("unique_id", ""),
"author_nickname": author.get("nickname", ""),
"views": metric(stats, "play_count"),
"likes": metric(stats, "digg_count"),
"comments": metric(stats, "comment_count"),
"shares": metric(stats, "share_count"),
})
time.sleep(1)
columns = [
"query", "observed_at", "video_id", "created_at", "description",
"share_url", "author_username", "author_nickname", "views",
"likes", "comments", "shares",
]
with csv_path.open("w", newline="", encoding="utf-8") as csv_file:
writer = csv.DictWriter(csv_file, fieldnames=columns)
writer.writeheader()
writer.writerows(rows)
print("Saved {} unique returned videos to {}".format(len(rows), csv_path))
if __name__ == "__main__":
main()
Här är count angivet som önskad urvalsstorlek per sökfras. Skriptet förutsätter inte att API:t måste returnera exakt så många objekt: det faktiska antalet rader beror på svaret. Pausen mellan anrop är en enkel metod för att styra takten, inte ett påstående om tjänstens gränser eller krav. Lägg till begränsade återförsök, felövervakning och regler för tillåten anropsfrekvens i ett produktionsschema, enligt villkoren för din plan.
Så läser du den färdiga tabellen
I CSV-filen motsvarar varje rad en unik returnerad video som hittats med en av sökfraserna. Fältet query visar var posten kommer ifrån, observed_at anger tidpunkten för ögonblicksbilden och video_id används för deduplicering. Beskrivningen och länken hjälper analytikern att kontrollera sammanhanget, medan de offentliga räknarna visar reaktionerna vid insamlingstillfället. För långsiktiga jämförelser bör du spara separata observationer i stället för att skriva över historiken för mätvärdena.
Antalet visningar, gilla-markeringar, kommentarer och delningar är en ögonblicksbild av den offentliga statistik som API:t returnerade vid anropstillfället. Uppgifter kan saknas i enskilda objekt, så ett tomt värde i CSV-filen betyder att det numeriska fältet saknades i svaret. Det är inte samma sak som noll och bör hanteras separat när sammanfattande mått beräknas. De hittade resultaten motsvarar dessutom urvalet för specifika sökord, region, tidsfilter och anropsparametrar. De beskriver de videor som faktiskt hämtades, inte allt innehåll eller hela plattformens målgrupp.
För en första bedömning av möjlig relevans kan du skapa en transparent regelbaserad tabell: träffar på problemformuleringar, omnämnanden av ett verktyg som används, frågor om pris eller jämförelser samt förekomst av ett konkret arbetsscenario. Spara helst de enskilda kännetecknen och en förklaring till bedömningen i stället för enbart en ogenomskinlig poäng. En video med en fråga om automatisk transkribering kan till exempel märkas ”granska: diskuterar kvalitet”, medan en video med allmänna innehållstips kan märkas ”låg ämnesrelevans”.
Använd AI utan att göra modellen till domare
När ett urval har samlats in kan en modell hjälpa till att märka upp beskrivningarna enligt ett förutbestämt schema: problem, nämnt verktyg, frågans ton och förekomst av tecken på produktval. Skicka bara de fält modellen behöver, till exempel beskrivningstexten och postens identifierare, och be den returnera fast JSON med etiketter och en kort motivering. Spara instruktionens version, modellen och resultatet tillsammans med originalraden, så att märkningen kan upprepas eller granskas manuellt på ett urval.
En bra instruktion till klassificeraren begränsar slutsatserna till observerbara kännetecken. Be den avgöra om texten innehåller ett uttryckligt problem med undertexter, en begäran om rekommendation av ett verktyg eller en diskussion om arbetsflöde. Lägg till kategorin ”otillräckligt sammanhang” när uppgifterna inte räcker. Modellen ska inte dra slutsatser om kreatörens identitet, köpintention eller demografiska egenskaper från en enda offentlig video. Resultatet är en lista med ämnen att analysera, inte en lista över personer som ska kontaktas automatiskt.
För att utvärdera märkningens kvalitet kan du ta ett slumpmässigt delurval och manuellt sätta samma etiketter. Jämför överensstämmelsen för varje etikett och granska felen: modellen kan till exempel tolka sarkasm som ett klagomål eller ett utbildande råd som personlig erfarenhet. Det är ofta mer användbart att förbättra ordlistan och instruktionen än att genast göra modellen mer avancerad. Spara originaltexter och länkar enligt den antagna lagrings- och åtkomstpolicyn.
Automatisering enligt schema och kvalitetskontroll
Efter en lyckad manuell körning kan skriptet schemaläggas med cron, en molnplattformstjänsts schemaläggare eller en orkestrerare som n8n. Den praktiska kedjan är densamma: läs listan med sökfraser, anropa API:t, kontrollera statusen, spara råsvaret, normalisera videorna, registrera nya ögonblicksbilder och skapa en rapport. Skicka nyckeln via exekveringsmiljöns mekanism för hemligheter, inte i en tabell, workflow-text eller ett felmeddelande.
Fyra kontroller är användbara i ett automatiserat jobb. För det första ska anropet lyckas och svaret vara JSON. För det andra ska den övergripande statusen ha det förväntade värdet. För det tredje ska hanteraren klara båda sökstrukturernas former och hantera saknade fält korrekt. För det fjärde ska antalet nya unika videor och antalet fel skrivas till loggen. Om inga resultat plötsligt hittas ska rapporten visa ett urval med noll resultat som status för körningen, i stället för att blanda ihop det med en vanlig lyckad rapport utan förklaring.
Lägg till paginering först efter att den första sidan har verifierats. Dokumentationen anger parametern cursor för sökrutten. Spara den mottagna token och skicka vidare den oförändrad i nästa anrop. Begränsa det högsta antalet sidor per sökterm och avsluta loopen när inga nya objekt tillkommer, nästa cursor saknas eller en redan behandlad cursor upprepas. En sådan gräns gör körningstiden och insamlingsvolymen hanterbara. Att en cursor finns gör det möjligt att fortsätta hämtningen, men garanterar inte fullständighet i förhållande till alla publicerade videor.
En ny körning samma dag kan returnera överlappande videor. Använd därför video-ID:t som en stabil nyckel för deduplicering och spara historiska ögonblicksbilder separat med observationsdatum. Om du behöver en sammanställning kan du bygga den ovanpå ögonblicksbilderna. Då går det att skilja en nyligen upptäckt video från en som förekom i flera sökningar eller hämtades igen vid ett senare tillfälle.
Mätvärden: vad som går att jämföra på ett rättvisande sätt
För operativ uppföljning är det användbart att mäta antalet unika videor per sökfras, andelen videor med en ifylld beskrivning, fördelningen av tillgängliga reaktioner och hur ofta vissa ämnen förekommer. När du jämför sökfraser bör parametrar och körningsperiod vara desamma. Om en körning använder this-week och en annan this-month kan skillnaden i volym bero på tidsfönstret och bör därför inte tolkas som ett förändrat intresse utan ytterligare analys.
För att jämföra mätvärden för en video över tid krävs flera ögonblicksbilder och en enhetlig lagringsmodell. Spara de ursprungliga värdena som de returnerades vid varje datum och beräkna sedan skillnaden mellan observationerna. Kalla inte skillnaden en ökning per dygn om det faktiska intervallet mellan körningarna varierade. På samma sätt kan en rangordning efter gilla-markeringar hjälpa till att hitta uppmärksammade videor i det insamlade urvalet, men den mäter inte kreatörens eller produktens kommersiella effektivitet.
Marknadsteamets slutrapport kan kombinera tre nivåer: exempel på målgruppens formuleringar med klickbara länkar, tematiska grupper av problem och en kvantitativ beskrivning av det insamlade urvalet. Varje slutsats bör åtföljas av antal observationer, sökfraser och insamlingsperiod. Det ger chefen sammanhang och analytikern möjlighet att upprepa filtreringen på samma rådata.
Vanliga misstag och hur du undviker dem
Att behandla ett tomt fält som ett nollvärde
Om statistik eller uppgifter om skaparen saknas lämnar koden ovan cellen tom. Det bevarar skillnaden mellan ett okänt värde och en uppmätt nolla. Ange uttryckligen hur saknade värden ska hanteras i analysen och redovisa hur många rader som uteslutits från en viss beräkning.
Att anta att sökningen alltid returnerar en enda array
I söksvaret förekommer aweme_list och nästlade element i search_item_list[].aweme_info. Hanteraren kontrollerar båda formerna och ignorerar element av fel typ. Om schemat ändras hjälper de sparade råsvaren dig att snabbt hitta den nya dataplatsen, medan testfixturer i JSON gör det möjligt att verifiera rättningen före nästa körning.
Att räkna samma video som en separat signal flera gånger
Samma video kan matcha flera sökord. I exemplet tas den med en enda gång i den slutliga CSV-filen, och sökfrasfältet visar den första matchningen i den aktuella ordningen. Om du behöver bevara alla kopplingar mellan video och sökfras bör du lagra dem i en separat kopplingstabell eller en lista över sökfraser för varje ID, i stället för att ta bort postens ursprung.
Att jämföra urval som inte är jämförbara
Sökord, region, tidsfilter, sortering och körningsdatum påverkar urvalet. Spara parametrarna tillsammans med svaret och ändra en faktor i taget när du jämför varianter. Då blir det lättare att avgöra om resultatförändringen beror på hur sökresultaten fungerar eller på ändrade experimentinställningar.
Att framställa korrelation som köpintention
Videobeskrivningar och offentliga räknare ger tecken på innehåll och publikreaktioner. De visar inte i sig vem som är redo att köpa, om en person har sett en annons eller hur stor konverteringen är. Använd dem för att formulera hypoteser, granska teman och förbereda innehåll. Mät försäljningseffektivitet med egna kampanjdata som kan samordnas med undersökningen vad gäller tid och målgrupp.
Så kan du bygga ut pipelinen
När grundversionen fungerar stabilt kan du lägga till en konfigurationsfil med en lista över sökfraser och körningsparametrar, så att ordlistan kan ändras utan att Python-koden redigeras. Nästa steg är en kopplingstabell för sökfraser och temakluster, till exempel ”igenkänningskvalitet”, ”redigeringshastighet” och ”export”. Teamet bör definiera och kontrollera sådana kategorier mot exempel. API:t returnerar sökdata; det är forskaren som bestämmer den semantiska strukturen.
En relationsdatabas kan ersätta CSV för lagring: använd tabeller för körningar, videor och ögonblicksbilder av mätvärden. Ett unikt index på video-ID:t skyddar katalogen mot dubbletter, medan ögonblicksbilder gör det möjligt att följa förändringar i tillgängliga räknare. Spara observationstid i UTC och versionen av normaliseraren. Om extraktionslogiken ändras kan arkiverad JSONL bearbetas på nytt och resultaten jämföras.
I n8n kan insamlingen köras enligt schema, medan normaliseringskoden körs i en separat Python-tjänst eller nod, om miljön har stöd för de nödvändiga operationerna. En modell behöver inte byggas in från början. Börja med att göra insamlingen stabil, mät sedan hur mycket tid manuell klassificering tar och vilka kategorier som återkommer. AI är motiverat när det effektiviserar ett konkret återkommande arbete och etiketterna går att kontrollera.
Om arbetsfrågan gäller regelbunden bevakning av ett visst konto i stället för sökning efter formuleringar finns en separat rutt, /getUserFeed, med parametrarna query, max_cursor och count i den officiella referensen. För en hashtagg finns /getHashtagFeed med parametern cursor. Det här är olika insamlingsscenarier: välj ändpunkt utifrån forskningsfrågan i stället för att ersätta en urvalstyp med en annan.
Resultat: ett reproducerbart urval i stället för ett bokmärkeskaos
Efter körningen har teamet två användbara resultat: ett arkiv med råsvar och en tabell med unika videor, sökterm, observationstid, länk, beskrivning och tillgängliga mätvärden. Utifrån dessa kan man gruppera målgruppens frågor manuellt, skicka texter till en kontrollerad klassificering, skapa en veckosammanställning och jämföra återkommande ögonblicksbilder. Koden hanterar uttryckligen anropsfel, kontrollerar den övergripande statusen, skiljer mellan två varianter av sökstrukturen och sparar saknade mätvärden som bortfall.
Det praktiska resultatet för teamet är ett mer transparent beslutsunderlag för vilka problem som bör undersökas i intervjuer, på en landningssida eller i ett reklambudskap. Om undersökningen kräver en annan datatyp kan du ändra sökfraserna eller använda en motsvarande dokumenterad rutt. Innan du anpassar pipelinen kan du kontrollera parametrarna i dokumentationen för TikTok API. Produktinformation och ingången till demon finns på sidan för TikTok Scraper API.
Det här tillvägagångssättet löser den ursprungliga uppgiften: att omvandla TikTok-sökningar till en reproducerbar undersökningsprocess. Skriptet samlar in de konkreta videor som returneras och sparar deras ursprung och ögonblicksbilder. Därefter omvandlar en människa eller en granskningsbar klassificerare innehållet till hypoteser om efterfrågan. Teamet får ett underlag för nästa beslut utan att blanda ihop offentliga innehållssignaler med bekräftade försäljningsresultat.