Python · YouTube

Monitorare le statistiche dei video YouTube con Python

YouTube mostra il numero attuale di visualizzazioni di un video, ma non come ci è arrivato. Se vuoi sapere quanto velocemente cresce un video – tuo, di un concorrente o di una campagna che hai pagato – devi annotare i numeri con regolarità. Questa guida costruisce un piccolo script che lo fa per te.

Una volta al giorno chiede a everydata.io visualizzazioni, like e commenti attuali di ogni video della tua lista, aggiunge una riga a un file CSV e stampa quante visualizzazioni ha guadagnato ogni video dall'ultima esecuzione. Se vuoi, rileva anche gli ultimi caricamenti di un canale, così i nuovi video vengono monitorati dal primo giorno.

Aggiornato il · di everydata.io

Cosa avrai alla fine

  • Un file CSV con una riga per video e per giorno: visualizzazioni, like, commenti.
  • La crescita delle visualizzazioni dal controllo precedente, stampata a ogni esecuzione.
  • Monitoraggio automatico dei nuovi caricamenti di un canale.

Cosa ti serve

  • Python 3.10 o superiore e pip install requests.
  • Una chiave API gratuita di everydata.io – creala qui – nella variabile d'ambiente EVERYDATA_API_KEY.
  • I video da monitorare: l'ID dopo v= nel link, oppure il link completo.

01Guarda cosa restituisce l'API per un video

L'endpoint video-details accetta un ID o un link del video in id e restituisce i numeri pubblici della pagina del video. Esempio documentato, abbreviato:

Risposta di esempio · GET /ytb/youtube-video-details
{
  "responseStatus": "PAGE_FOUND",
  "responseMessage": "Page successfully found!",
  "videoId": "kJQP7kiw5Fk",
  "title": "Luis Fonsi - Despacito ft. Daddy Yankee",
  "channelName": "LuisFonsiVEVO",
  "viewCount": 9125159593,
  "likeCount": 56673581,
  "likeCountText": "56M",
  "commentCount": 4300000,
  "publishedAt": "2017-01-12T21:00:02-08:00",
  "duration": 282
}

viewCount, likeCount e commentCount sono semplici numeri, pronti da salvare e confrontare. likeCountText è l'etichetta arrotondata che YouTube mostra nella pagina.

02Registra i numeri a ogni esecuzione

Lo script legge dal file CSV l'ultimo numero di visualizzazioni di ogni video, recupera i valori attuali, aggiunge una nuova riga e stampa la differenza.

monitor.py
"""Record views, likes and comments of YouTube videos and print the growth since the last check."""
import csv
import os
import re
import time
from datetime import datetime, timezone
from pathlib import Path

import requests

API = "https://api.everydata.io"
KEY = os.environ["EVERYDATA_API_KEY"]
CSV_FILE = Path("video_stats.csv")
VIDEOS = ["kJQP7kiw5Fk"]  # video IDs or full YouTube links


def api_get(path: str, params: dict) -> dict:
    """GET an everydata.io endpoint. Waits when rate limited (429) and retries a failed page load (5xx) once."""
    retried = False
    for _ in range(4):
        resp = requests.get(f"{API}{path}", params=params, headers={"x-api-key": KEY}, timeout=60)
        if resp.status_code == 429:
            # Too many requests at once. The answer says how long to wait: "... Try again in 12 seconds."
            wait = re.search(r"in (\d+) seconds", resp.text)
            time.sleep(int(wait.group(1)) + 1 if wait else 60)
            continue
        if resp.status_code >= 500 and not retried:
            retried = True  # 5xx answers are not counted against your quota
            time.sleep(10)
            continue
        resp.raise_for_status()  # 4xx (wrong key, quota used up, bad parameter) or a second 5xx
        return resp.json()
    raise RuntimeError("still rate limited after several waits – try again later")


def video_details(video: str) -> dict:
    return api_get("/ytb/youtube-video-details", {"id": video})


def last_views() -> dict[str, int]:
    """Most recent view count per video from earlier runs."""
    if not CSV_FILE.exists():
        return {}
    with CSV_FILE.open(newline="") as f:
        return {r["video_id"]: int(r["views"]) for r in csv.DictReader(f) if r["views"]}


def main() -> None:
    before = last_views()
    now = datetime.now(timezone.utc).isoformat(timespec="seconds")
    new_file = not CSV_FILE.exists()

    with CSV_FILE.open("a", newline="") as f:
        writer = csv.writer(f)
        if new_file:
            writer.writerow(["checked_at", "video_id", "title", "views", "likes", "comments"])
        for video in VIDEOS:
            try:
                v = video_details(video)
            except (requests.RequestException, RuntimeError) as exc:
                print(f"{video}: could not check this time ({exc}) – the next run tries again")
                continue  # one failed video does not stop the others
            video_id = v.get("videoId") or video
            views = v.get("viewCount")
            writer.writerow([now, video_id, v.get("title"), views or "",
                             v.get("likeCount") or "", v.get("commentCount") or ""])
            if views is not None and video_id in before:
                print(f"{v.get('title')}: +{views - before[video_id]:,} views since the last check")


if __name__ == "__main__":
    main()

Eseguilo con python3 monitor.py. Dalla seconda esecuzione in poi vedi righe come “+12,345 views since the last check”. api_get attende e prosegue quando invii troppe richieste insieme (429) e riprova una volta un caricamento di pagina fallito (5xx); un video che fallisce ancora viene segnalato e ripreso all'esecuzione successiva.

03Rileva i nuovi video di un canale

Invece di aggiungere a mano ogni nuovo video, chiedi gli ultimi caricamenti di un canale e inseriscili nella lista. L'endpoint channel-videos accetta un ID o un link del canale.

monitor.py (da aggiungere sotto video_details)
def latest_uploads(channel: str) -> list[str]:
    """IDs of the newest regular videos of a channel (channel ID or URL such as https://www.youtube.com/@WWE)."""
    data = api_get("/ytb/youtube-channel-videos", {"id": channel, "filter": "videos_latest"})
    return [item["videoId"] for item in data.get("items", []) if item.get("type") == "video"]


# In main(): watch the five newest uploads of a channel as well as your fixed list
# for video in VIDEOS + latest_uploads("https://www.youtube.com/@WWE")[:5]:
Risposta di esempio · GET /ytb/youtube-channel-videos
{
  "responseStatus": "PAGE_FOUND",
  "responseMessage": "Page successfully found!",
  "channelId": "UCJ5v_MCY6GNUBTO8-D3XoAg",
  "filter": "videos_latest",
  "items": [
    {
      "type": "video",
      "videoId": "b7kl_pcHa0A",
      "title": "Blake Monroe vows to get payback against Giulia: SmackDown exclusive, Sept. 18, 2026",
      "viewCount": 6800,
      "publishedTimeText": "47 minutes ago"
    }
  ]
}

04Eseguilo una volta al giorno

Pianifica lo script con cron (Mac, Linux), l'Utilità di pianificazione di Windows o un job CI pianificato:

crontab
0 6 * * * cd /home/you/yt-monitor && EVERYDATA_API_KEY=ds_your_key /usr/bin/python3 monitor.py >> monitor.log 2>&1

Ogni lookup di un video e ogni lookup di un canale è una richiesta. Un esempio: tre video controllati una volta al giorno fanno circa 90 richieste al mese, entro il piano gratuito da 100. Per dati giornalieri su molti video, consulta i prezzi.

Apri video_stats.csv in un foglio di calcolo e traccia le visualizzazioni rispetto a checked_at per vedere la curva di crescita.

Endpoint usati in questa guida

GET/ytb/youtube-video-details

Video Details · API YouTube

GET/ytb/youtube-channel-videos

Channel Videos · API YouTube

Tutti i parametri nella API reference

Provalo con i tuoi dati

Il piano gratuito include 100 richieste al mese, utilizzabili su ogni piattaforma – abbastanza per seguire questa guida dall'inizio alla fine.