Aperçu
Suit un ensemble de playlists YouTube qui vous intéressent (contenu de cours, présentations sectorielles, chaînes concurrentes) et alerte lorsque des vidéos sont supprimées ou rendues privées. Essentiel pour les éducateurs préservant l'équité des liens et les chercheurs suivant les événements de modération de la plateforme.
Déclencheur
Planification Cron (toutes les 6 heures)
Planification
Toutes les 6 heures
Étapes du workflow
Charger les playlists suivies
Lire les IDs de playlist depuis un fichier de configuration (généralement 5 à 100 playlists).
Récupération de playlist YouTube Scavio
Extraire la liste actuelle des vidéos via la plateforme YouTube Scavio avec le paramètre de playlist.
Diff vs instantané
Comparer avec le dernier instantané stocké et identifier les ID de vidéos supprimées.
Résoudre les vidéos supprimées
Essayer de récupérer chaque vidéo supprimée pour distinguer supprimée, privée ou géo-bloquée.
Enregistrer les événements de retrait
Persister dans Postgres avec l'ID de playlist, l'ID de vidéo, la raison du retrait, l'horodatage.
Alerte Slack en cas de retrait
Publier une notification avec le titre de la vidéo (depuis l'instantané) et la raison du retrait.
Implémentation Python
import os, requests, json
API_KEY = os.environ["SCAVIO_API_KEY"]
H = {"x-api-key": API_KEY}
PLAYLISTS = ["PLxxxxxxxxxxxxxxxxxxxxxx"]
def fetch(playlist_id):
r = requests.post("https://api.scavio.dev/api/v1/search",
headers=H, json={"platform": "youtube", "playlist": playlist_id})
return {v["id"]: v["title"] for v in r.json().get("videos", [])}
prev = json.load(open("snapshot.json")) if os.path.exists("snapshot.json") else {}
cur = {p: fetch(p) for p in PLAYLISTS}
for p, videos in cur.items():
removed = set(prev.get(p, {})) - set(videos)
for vid in removed:
print(f"REMOVED {vid} from {p}: {prev[p][vid]}")
json.dump(cur, open("snapshot.json", "w"))Implémentation JavaScript
const API_KEY = process.env.SCAVIO_API_KEY;
const H = { "x-api-key": API_KEY, "content-type": "application/json" };
const PLAYLISTS = ["PLxxxxxxxxxxxxxxxxxxxxxx"];
const fs = require("fs");
async function fetchPl(id) {
const r = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST", headers: H,
body: JSON.stringify({ platform: "youtube", playlist: id })
}).then(r => r.json());
return Object.fromEntries((r.videos || []).map(v => [v.id, v.title]));
}
const prev = fs.existsSync("snapshot.json") ? JSON.parse(fs.readFileSync("snapshot.json")) : {};
const cur = {};
for (const p of PLAYLISTS) cur[p] = await fetchPl(p);
for (const [p, videos] of Object.entries(cur)) {
const removed = Object.keys(prev[p] || {}).filter(k => !videos[k]);
for (const vid of removed) console.log("REMOVED", vid, prev[p][vid]);
}
fs.writeFileSync("snapshot.json", JSON.stringify(cur));Plateformes utilisées
YouTube
Recherche de vidéos avec transcriptions et métadonnées