jsonscraper

Slik sammenligner du konkurrenters TikTok-videoer med offentlige måltall: en Python-pipeline

Samle resultater fra flere søk, fjern duplikater og sammenlign videoer etter visninger, likerklikk og kommentarer

Redaksjonelle retningslinjer Meld fra om en feil

To team publiserer videoer om et lignende produkt, men vurderer dem manuelt etter ulike kriterier: Det ene husker visningstallene, det andre kommentarene, og det tredje lagrer lenker i en chat. En uke senere er det vanskelig å vite hvilke formater som går igjen hos konkurrentene, hvilke innlegg som får tydelige reaksjoner, og hva som har endret seg siden forrige gjennomgang.

Løsningen er å samle et avgrenset og reproduserbart utvalg av offentlige videoer med forhåndsdefinerte søkeord, lagre den opprinnelige JSON-en og lage en tabell med ensartede felt. Da kan videoene sammenlignes i én arbeidsflyt, uten at tilfeldige observasjoner blandes sammen med konklusjoner om markedet. Nedenfor finner du en oppskrift på enkel konkurrentovervåking i Python med TikTok Scraper API fra jsonscraper.

Definer analysebehovet først

Datainnsamling er nyttig når det på forhånd er klart hvilken beslutning resultatene skal bidra til. Et markedsføringsteam hos en produsent av sportsflasker kan for eksempel undersøke hvordan konkurrentene viser fram produktene i korte videoer: gjennom demonstrasjoner, utpakking, sammenligninger eller brukerreaksjoner. Det er ikke nødvendig å kopiere hele TikTok. Noen få målrettede søk og en repeterbar gjennomgang av videoene API-et returnerer, er nok.

Formuler spørsmålet slik at det kan undersøkes: «Hvilke formater for beskrivelser og demonstrasjoner forekommer blant videoene som er publisert for de fem viktigste søkefrasene våre, og hvilke av de funnede videoene har de høyeste nåværende visnings- og reaksjonstallene?» Denne formuleringen skiller mellom to analyselag. Tekst og beskrivelse kan brukes til å gruppere kreative tilnærminger, mens tellere for visninger, likerklikk, kommentarer og delinger gir et øyeblikksbilde av offentlige reaksjoner på innsamlingstidspunktet.

Dette øyeblikksbildet er nyttig når man skal prioritere manuell gjennomgang og følge med på endringer. Det beskriver videoene som ble returnert for bestemte søk, parametere og tidspunkt. En presis konklusjon er derfor «utpakking forekommer ofte i utvalget vårt» eller «denne videogrup­pen har for øyeblikket høyere medianvisninger». Et slikt avgrenset analysegrunnlag hjelper teamet med å velge hypoteser for eget innhold.

Utform en liten datapipeline

Del arbeidet inn i fire trinn: innsamling, lagring av råsvaret, normalisering og analyse. Innsamlingen kaller API-et for hvert godkjente søkeord. Råsvaret lagres i sin helhet, slik at verdiene kan kontrolleres senere. Normaliseringen gjør den nøstede JSON-strukturen om til tabellrader, og analysen beregner måltall og grupperer videoene etter søkeord eller manuelt tildelt format.

  • Innsamling. Be om et bestemt antall resultater for hvert søkeord, med samme region og sortering.
  • Arkiv. Lagre den opprinnelige JSON-en og tidspunktet for innhenting, slik at de uttrukne verdiene kan kontrolleres.
  • Normalisering. Ta med video-ID, lenke, beskrivelse, opphavsperson, publiseringstidspunkt og tilgjengelige tellere.
  • Kvalitetskontroll. Fjern duplikater basert på ID, marker manglende verdier og lagre søkeordet som førte til videoen.
  • Sammenligning. Beregn egne måltall utelukkende fra tilgjengelige kildefelt, og sammenlign grupper innenfor samme øyeblikksbilde.

Denne tilnærmingen er bedre enn en liste med lenker fordi den bevarer hvor hver rad kommer fra, og gjør det mulig å skille mellom at samme video dukker opp igjen og at det er snakk om nytt innhold. Lagre også innsamlingsdatoen: offentlige tellere kan endre seg, og verdien i dagens svar bør derfor ikke tolkes som en permanent egenskap ved videoen.

Dette støtter TikTok Scraper API

For videosøk med tekst beskriver jsonscrapers dokumentasjon GET-endepunktet /searchVideo på basisadressen https://tiktok.evelode.com. Den obligatoriske parameteren er keyword. Du kan også bruke count, cursor, region, date_posted, sort_by og cache_timeout. Dokumentasjonen oppgir sorteringsalternativene most-liked, relevance og date-posted, og publiseringsperiodene yesterday, this-week, this-month, last-3-months, last-6-months og all-time. Kontroller parameternavn og funksjoner i oversikten over TikTok-endepunktene.

Nøkkelen sendes i spørringsparameteren license_key. I et skript som skal brukes i praksis, bør den ligge i miljøvariabelen JSONSCRAPER_TIKTOK_LICENSE_KEY, ikke i kildefilen, en tabell eller en kjørelogg. Kontroller øverste nivå i svaret for status, og behandle deretter objektet tiktok. Søkesvaret kan inneholde listen aweme_list og dessuten search_item_list, der videoopplysningene ligger under aweme_info. Koden nedenfor håndterer begge formatene.

Bekreftede observasjoner fra søkesvar omfatter video-ID, beskrivelse, publiseringstidspunkt, lenke, opplysninger om opphavspersonen og måltall som visninger, likerklikk, kommentarer, lagringer og delinger. Enkelte felt kan mangle i en bestemt oppføring. La slike verdier stå tomme i tabellen i stedet for å erstatte dem med null: Null betyr at verdien er målt til null, mens et tomt felt betyr at verdien manglet i det mottatte objektet.

Et enkelt Python-eksempel

Skriptet nedenfor gjør ett kall per søkeord, lagrer hele svaret i en JSON-fil og lager en CSV-fil for et regneark eller videre behandling. Det er laget for Python 3.8+ og bruker bare standardbiblioteket. Angi lisensnøkkelen som en miljøvariabel før kjøring. Tilpass søkeordlisten og antall resultater etter behov.

import csv
import json
import os
import time
from datetime import datetime, timezone
from pathlib import Path
from urllib.parse import urlencode
from urllib.request import urlopen

BASE_URL = "https://tiktok.evelode.com/searchVideo"
LICENSE_KEY = os.environ["JSONSCRAPER_TIKTOK_LICENSE_KEY"]
KEYWORDS = ["termosflaske", "sportsflaske", "utpakking av flaske"]
REGION = "US"
COUNT = 20


def request_search(keyword):
    params = {
        "license_key": LICENSE_KEY,
        "keyword": keyword,
        "count": COUNT,
        "region": REGION,
        "sort_by": "relevance",
        "date_posted": "this-month",
    }
    url = BASE_URL + "?" + urlencode(params)
    with urlopen(url, timeout=60) as response:
        return json.loads(response.read().decode("utf-8"))


def extract_videos(payload):
    if payload.get("status") != "ok":
        raise RuntimeError("API returned a non-ok status")

    tiktok = payload.get("tiktok") or {}
    rows = []

    for item in tiktok.get("aweme_list") or []:
        if isinstance(item, dict):
            rows.append(item)

    for item in tiktok.get("search_item_list") or []:
        video = item.get("aweme_info") if isinstance(item, dict) else None
        if isinstance(video, dict):
            rows.append(video)

    return rows, tiktok


Path("raw").mkdir(exist_ok=True)
seen = set()
records = []

for keyword in KEYWORDS:
    payload = request_search(keyword)
    collected_at = datetime.now(timezone.utc).isoformat()
    safe_name = keyword.replace(" ", "_")
    raw_path = Path("raw") / (safe_name + ".json")
    raw_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")

    videos, tiktok = extract_videos(payload)
    for video in videos:
        video_id = video.get("aweme_id")
        if not video_id:
            continue
        dedupe_key = (keyword, video_id)
        if dedupe_key in seen:
            continue
        seen.add(dedupe_key)

        stats = video.get("statistics") or {}
        author = video.get("author") or {}
        records.append({
            "collected_at": collected_at,
            "keyword": keyword,
            "video_id": video_id,
            "url": video.get("share_url"),
            "created_at_epoch": video.get("create_time"),
            "description": video.get("desc"),
            "author": author.get("nickname"),
            "username": author.get("unique_id"),
            "views": stats.get("play_count"),
            "likes": stats.get("digg_count"),
            "comments": stats.get("comment_count"),
            "shares": stats.get("share_count"),
            "saves": stats.get("collect_count"),
            "cursor": tiktok.get("cursor"),
        })

    time.sleep(1)

fieldnames = [
    "collected_at", "keyword", "video_id", "url", "created_at_epoch",
    "description", "author", "username", "views", "likes", "comments",
    "shares", "saves", "cursor",
]
with open("tiktok_creatives.csv", "w", newline="", encoding="utf-8") as output:
    writer = csv.DictWriter(output, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(records)

print("Saved", len(records), "video rows to tiktok_creatives.csv")

Skriptet lagrer søkeordet sammen med videoen, noe som er viktig hvis samme video blir funnet gjennom flere søk. Her dedupliseres det innenfor hvert søkeord, så samme ID kan få en egen rad for ulike søk. Hvis du vil ha én samlet tabell uten gjentakelser, kan du bytte ut nøkkelen (keyword, video_id) med video_id og samle søkeordene i en liste eller en egen koblingstabell.

Koden gjør med hensikt bare ett kall per søkeord og henter ikke automatisk flere sider. Hvis du trenger neste side, beskriver dokumentasjonen cursor som verdien for å bla videre i resultatene, hentet fra forrige svar. Bruk den som en ugjennomsiktig verdi, uten å beregne den selv. Kontroller pagineringsformatet med et testsvar for den aktuelle arbeidsflyten, og stopp når det ikke finnes flere resultater eller en ny markør.

Slik lager du en sammenlignbar tabell

CSV-filen kan åpnes i et regneark, lastes inn i en database eller brukes i Python til å beregne sammendrag. I en første rapport kan du gruppere radene etter innsamlingsdato, søkeord og videoformat. Det er best å merke formatet etter å ha sett på beskrivelsen og selve videoen, for eksempel «demonstrasjon», «utpakking», «anmeldelse» eller «sammenligning». En liten utvalgsgruppe kan merkes manuelt, eller en modell kan foreslå foreløpige etiketter som deretter kontrolleres av et menneske.

Hvis du automatiserer merking av tekster, bør du bare sende modellen feltene den trenger, for eksempel beskrivelse og ID, og be om én etikett fra en forhåndsgodkjent liste. Lagre den opprinnelige beskrivelsen separat fra klassifiseringsresultatet. Da kan analytikeren kontrollere tvilsomme etiketter og beregne rapporten på nytt etter en endring i taksonomien, uten å sende en ny forespørsel til API-et.

Bruk verdier fra samme innsamlingstidspunkt når du beregner sammenligningsmåltall. Forholdet mellom likerklikk og visninger kan for eksempel beregnes som likes / views når begge feltene finnes og visningstallet er større enn null. Tilsvarende kan du beregne andelen kommentarer eller delinger. Disse forholdstallene beskriver den nåværende offentlige telleren for den aktuelle videoen; de måler ikke rekkevidde blant en bestemt målgruppe, fullførte visninger eller konverteringer. Når du tar forretningsbeslutninger, bør du sammenholde dem med egne kampanjer og bruke dem som veiledning til valg av ideer, ikke som et lovet resultat av å gjenta et annet formats suksess.

Medianen er ofte mer nyttig enn gjennomsnittet når utvalget inneholder noen få svært populære videoer. Sammenlign medianen for visninger og reaksjoner mellom grupper bare når innsamlingsreglene er de samme: samme søk, region, tidsfilter og omtrent samme tidspunkt for øyeblikksbildet. Registrer kjøreparametrene sammen med datoen. Hvis søket eller utvalget endres, kan forskjellen mellom to rapporter skyldes at datasettet ble satt sammen på en annen måte.

Nye kjøringer og kontroll av endringer

Hvis en engangsanalyse skal bli til løpende overvåking, kan du kjøre skriptet etter en tidsplan, for eksempel daglig eller ukentlig, og legge innsamlingsdatoen til hver oppføring. Lagre par av «tidspunkt for øyeblikksbilde — tellerværdi» for hver video. Da kan du se hvordan de offentlige måltallene har endret seg mellom observasjonene, samtidig som hvert målepunkt beholdes separat. Ikke overskriv gamle tellere med de nyeste, for da forsvinner utviklingen over tid.

I produksjon bør du flytte rå JSON fra den lokale mappen til objektlagring eller et annet arkiv, og legge normaliserte rader i en database med en unik nøkkel, for eksempel kombinasjonen av video-ID og innsamlingstidspunkt. Legg til en feillogg som ikke inneholder den hemmelige nøkkelen, en grense for antall nye forsøk og varsling når et kall mislykkes. Ved en midlertidig feil kan du prøve på nytt etter en pause. Ved en strukturell feil bør du heller lagre svaret og merke kjøringen for kontroll, slik at en feil ikke ubemerket gir en tom rapport.

Ikke bruk cursor som en permanent identifikator for en undersøkelse: Det er en markør for å fortsette en resultatliste. Lagre den sammen med parameterne for den aktuelle forespørselen, og bruk den bare til å fortsette den listen. Ikke bland sider fra ulike søkeord. Registrer også hvor mange resultater som faktisk ble behandlet: Den forespurte verdien for count angir ønsket størrelse på svaret, men garanterer ikke full dekning av alle relevante innlegg.

Slik kan du utvide arbeidsflyten

Hvis søkeutvalget inneholder for mye støy, kan du i stedet følge bestemte offentlige profiler eller emneknagger. Dokumentasjonen inneholder endepunktene /getUserFeed og /getHashtagFeed med parametere for søk og paginering. Dette er andre utvalg med egne regler for videre innhenting: Profilstrømmen bruker max_cursor, mens emneknaggstrømmen bruker cursor. Koble dem til som egne kilder, og lagre kildetype og parametere slik at søketreff på søkeord ikke blandes sammen med profil- eller emneknagginnlegg.

For team uten egen infrastruktur kan CSV-data sendes til Google Sheets via API-et. Dokumentasjonen for Google Sheets API beskriver hvordan celleverdier kan leses og skrives. Opprett egne ark for råkjøringer, normaliserte videoer og sammendrag. Dette er praktisk når flere skal merke videoer sammen. Når historikken blir for stor for et regneark, kan radene flyttes til en SQL-database med de samme feltene og den samme informasjonen om hvor dataene kommer fra.

En fornuftig oppgave for en AI-agent er å lage et kort sammendrag av innsamlede og normaliserte oppføringer: gruppere beskrivelser, foreslå formater og peke ut uvanlige verdier. Ikke be agenten trekke konklusjoner om hele plattformen ut fra et lite resultatsett. Oppgi periode, søkeliste og antall rader, be den vise til video-ID-er og la usikre eller manglende felt stå tomme. Analytikeren kan deretter kontrollere eksemplene via de lagrede lenkene.

Dette får du ut av arbeidet

Når oppsettet er på plass, får teamet et reproduserbart register over funne videoer med ID-er, lenker, beskrivelser, opphavspersoner, publiseringstidspunkter og tilgjengelige offentlige tellere. Det lagrede råsvaret gjør det mulig å kontrollere transformasjonen, mens CSV-filen gjør det enkelt å sortere videoer, filtrere på søkeord og sammenligne øyeblikksbilder fra ulike datoer. Ut fra dette kan teamet lage en ukentlig oppsummering av hvilke formater som gikk igjen, hvilke innlegg som bør undersøkes nærmere, og hvilke kreative hypoteser som er verdt å teste i eget innhold.

Det praktiske resultatet er ikke en universell konkurrentrangering, men et strukturert utvalg med tydelig opphav. Kvaliteten avhenger av søkene, filtrene og observasjonsperioden du velger. Ta derfor vare på innsamlingsparametrene, kontroller enkeltvideoer manuelt og skill mellom tilgjengelige måltall og tolkning. Slik kan teamet erstatte spredte bokmerker med sammenlignbare data og diskutere kreativt innhold med utgangspunkt i konkrete eksempler.

Du kan kontrollere søkeendepunktet og parameterne i den offisielle jsonscraper-dokumentasjonen. Beskrivelse av tjenesten og tilgang finner du på siden for TikTok Scraper API. Begynn med noen få søkefraser, lagre ett testsvar og kontroller strukturen før du setter opp en tidsplan.

People

No people listed for this article yet.

Keep readingSlik finner du tidlige signaler på TikTok-trender: automatisk overvåking av søkeresultater
Read the next article

Gjør det du leser til en fungerende integrasjon

Utforsk jsonscrapers API-er for sosiale data, test forespørsler og bygg neste arbeidsflyt.

Utforsk API-er