Torna al blog

Come raccogliere dati da YouTube per sistemi RAG: parsing di sottotitoli e metadati con Python

Guida passo passo per la raccolta di dati YouTube per l'addestramento di sistemi RAG: lavoro con API, parsing di sottotitoli e metadati, configurazione di proxy per la scalabilità.

📅6 marzo 2026
```html

I sistemi RAG (Retrieval-Augmented Generation) richiedono dati di qualità per l'addestramento. YouTube è una vasta fonte di contenuti strutturati: video con sottotitoli, metadati e commenti. In questo articolo vedremo come raccogliere efficacemente i dati di YouTube per RAG, evitando blocchi e rispettando i limiti dell'API.

Che cos'è RAG e perché sono necessari i dati di YouTube

RAG (Retrieval-Augmented Generation) è un approccio alla costruzione di sistemi AI, dove il modello linguistico è integrato con una base di conoscenze. Invece di fare affidamento solo sui dati su cui il modello è stato addestrato, RAG estrae informazioni rilevanti da una fonte esterna e le utilizza per generare risposte.

YouTube contiene milioni di ore di contenuti con sottotitoli in diverse lingue. Questo rende la piattaforma una fonte preziosa di dati per i sistemi RAG in vari settori:

  • Sistemi educativi — lezioni, tutorial, corsi con timestamp
  • Documentazione tecnica — video guide sulla programmazione, DevOps, configurazione software
  • Basi di conoscenza mediche — lezioni di medici, analisi di casi clinici
  • Analisi aziendale — interviste con esperti, casi studio, panoramiche di mercato
  • Supporto ai prodotti — recensioni di prodotti, FAQ in formato video

Il vantaggio dei dati di YouTube è la presenza di una struttura: sottotitoli con timestamp, metadati (categorie, tag), contesto sociale (commenti, like). Tutto ciò aiuta il sistema RAG a comprendere non solo il contenuto, ma anche il contesto delle informazioni.

Quali dati di YouTube sono utili per i sistemi RAG

Per il funzionamento efficace di un sistema RAG è necessario raccogliere diversi tipi di dati. Ogni tipo risolve le proprie problematiche nel processo di estrazione e generazione delle informazioni.

Sottotitoli (Transcripts)

La principale fonte di dati testuali. YouTube fornisce due tipi di sottotitoli:

  • Automatici — generati dagli algoritmi di riconoscimento vocale di Google. Disponibili per la maggior parte dei video in inglese e in altre lingue popolari. Precisione dell'85-95% a seconda della qualità audio.
  • Manuali — caricati dagli autori o dalla comunità. Più precisi, spesso contengono formattazione e contesto aggiuntivo.

I sottotitoli includono timestamp, il che consente di collegare il testo a momenti specifici del video. Questo è fondamentale per creare collegamenti precisi alle fonti nelle risposte RAG.

Metadati video

I metadati aiutano il sistema RAG a comprendere il contesto e la rilevanza delle informazioni:

Tipo di dati Applicazione in RAG
Titolo e descrizione Ricerca semantica, definizione del tema
Tag e categorie Classificazione dei contenuti, filtraggio
Data di pubblicazione Rilevanza delle informazioni (importante per argomenti tecnici)
Durata Valutazione della profondità di trattazione del tema
Statistiche (visualizzazioni, like) Valutazione della qualità e popolarità della fonte
Informazioni sul canale Determinazione dell'autorevolezza della fonte

Commenti

I commenti contengono contesto aggiuntivo: domande degli spettatori, chiarimenti degli autori, discussioni. Per i sistemi RAG questo è prezioso, poiché:

  • I commenti spesso contengono FAQ sul tema del video
  • Gli autori possono pubblicare correzioni e aggiunte
  • Le discussioni rivelano diversi punti di vista sul problema

Lavorare con YouTube Data API v3: configurazione e limiti

YouTube Data API v3 è il modo ufficiale per ottenere dati. Fornisce accesso a metadati, statistiche, commenti. I sottotitoli vengono ottenuti tramite metodi separati.

Ottenere la chiave API

Per lavorare con l'API è necessaria una chiave dalla Google Cloud Console:

  1. Vai su console.cloud.google.com
  2. Crea un nuovo progetto o seleziona uno esistente
  3. Abilita YouTube Data API v3 nella sezione "APIs & Services"
  4. Crea credenziali (Credentials) → chiave API
  5. Copia la chiave — sarà necessaria per tutte le richieste

Limiti e quote

L'API di YouTube utilizza un sistema di quote. Ogni richiesta "costa" un certo numero di unità:

Operazione Costo in quote
Ricerca video (search.list) 100 unità
Ottenere dati video (videos.list) 1 unità
Ottenere commenti (commentThreads.list) 1 unità

Il limite giornaliero predefinito è di 10.000 unità. Questo equivale a circa 100 richieste di ricerca o 10.000 richieste di metadati. Per aumentare la quota è necessario presentare una richiesta a Google.

Esempio base di utilizzo dell'API

import requests

API_KEY = 'la_tua_chiave_api'
BASE_URL = 'https://www.googleapis.com/youtube/v3'

# Ricerca video per query
def search_videos(query, max_results=10):
    url = f'{BASE_URL}/search'
    params = {
        'part': 'snippet',
        'q': query,
        'type': 'video',
        'maxResults': max_results,
        'key': API_KEY
    }
    
    response = requests.get(url, params=params)
    return response.json()

# Ottenere metadati video
def get_video_details(video_id):
    url = f'{BASE_URL}/videos'
    params = {
        'part': 'snippet,contentDetails,statistics',
        'id': video_id,
        'key': API_KEY
    }
    
    response = requests.get(url, params=params)
    return response.json()

# Esempio di utilizzo
results = search_videos('tutorial di machine learning', max_results=5)
for item in results.get('items', []):
    video_id = item['id']['videoId']
    title = item['snippet']['title']
    print(f'ID: {video_id}, Titolo: {title}')
    
    # Otteniamo informazioni dettagliate
    details = get_video_details(video_id)
    stats = details['items'][0]['statistics']
    print(f"Visualizzazioni: {stats.get('viewCount')}, Mi piace: {stats.get('likeCount')}")

Parsing dei sottotitoli video: automatici e manuali

YouTube Data API v3 non fornisce accesso diretto ai sottotitoli. Per ottenerli vengono utilizzati metodi alternativi.

Utilizzo della libreria youtube-transcript-api

Il modo più semplice è la libreria youtube-transcript-api per Python. Essa estrae i sottotitoli direttamente, senza chiave API:

from youtube_transcript_api import YouTubeTranscriptApi

# Ottenere sottotitoli
video_id = 'dQw4w9WgXcQ'

try:
    # Tentativo di ottenere sottotitoli in russo, se non disponibili, in inglese
    transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['ru', 'en'])
    
    # Stampa dei sottotitoli con timestamp
    for entry in transcript:
        start_time = entry['start']
        duration = entry['duration']
        text = entry['text']
        print(f"[{start_time:.2f}s] {text}")
        
except Exception as e:
    print(f"Errore durante l'ottenimento dei sottotitoli: {e}")

# Ottenere l'elenco delle lingue disponibili
transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
for transcript in transcript_list:
    print(f"Lingua: {transcript.language}, Automatici: {transcript.is_generated}")

La libreria determina automaticamente i sottotitoli disponibili e può tradurli in altre lingue (se YouTube offre tale possibilità).

Elaborazione dei timestamp per RAG

Per i sistemi RAG è importante mantenere il legame tra il testo e i timestamp. Questo consente di creare collegamenti precisi alle fonti:

def format_timestamp(seconds):
    """Conversione dei secondi nel formato MM:SS"""
    minutes = int(seconds // 60)
    secs = int(seconds % 60)
    return f"{minutes:02d}:{secs:02d}"

def create_chunks_with_timestamps(transcript, chunk_size=500):
    """Divisione dei sottotitoli in chunk mantenendo i timestamp"""
    chunks = []
    current_chunk = ""
    chunk_start_time = 0
    
    for i, entry in enumerate(transcript):
        if len(current_chunk) == 0:
            chunk_start_time = entry['start']
        
        current_chunk += entry['text'] + " "
        
        # Se abbiamo raggiunto la dimensione desiderata o la fine dei sottotitoli
        if len(current_chunk) >= chunk_size or i == len(transcript) - 1:
            chunks.append({
                'text': current_chunk.strip(),
                'start_time': chunk_start_time,
                'timestamp': format_timestamp(chunk_start_time),
                'video_id': video_id
            })
            current_chunk = ""
    
    return chunks

# Utilizzo
transcript = YouTubeTranscriptApi.get_transcript(video_id)
chunks = create_chunks_with_timestamps(transcript)

for chunk in chunks[:3]:  # Prime 3 chunk
    print(f"[{chunk['timestamp']}] {chunk['text'][:100]}...")

Raccolta di metadati: titoli, descrizioni, tag

I metadati arricchiscono il contesto per il sistema RAG. Ecco un esempio completo di raccolta di tutti i dati necessari:

import requests
from datetime import datetime

def collect_video_metadata(video_id, api_key):
    """Raccolta di metadati completi del video"""
    url = f'https://www.googleapis.com/youtube/v3/videos'
    params = {
        'part': 'snippet,contentDetails,statistics,topicDetails',
        'id': video_id,
        'key': api_key
    }
    
    response = requests.get(url, params=params)
    data = response.json()
    
    if 'items' not in data or len(data['items']) == 0:
        return None
    
    item = data['items'][0]
    snippet = item['snippet']
    stats = item.get('statistics', {})
    content = item.get('contentDetails', {})
    
    metadata = {
        'video_id': video_id,
        'title': snippet['title'],
        'description': snippet['description'],
        'channel_title': snippet['channelTitle'],
        'channel_id': snippet['channelId'],
        'published_at': snippet['publishedAt'],
        'tags': snippet.get('tags', []),
        'category_id': snippet.get('categoryId'),
        'duration': content.get('duration'),
        'view_count': int(stats.get('viewCount', 0)),
        'like_count': int(stats.get('likeCount', 0)),
        'comment_count': int(stats.get('commentCount', 0)),
        'topics': item.get('topicDetails', {}).get('topicCategories', [])
    }
    
    return metadata

# Esempio di utilizzo
metadata = collect_video_metadata('dQw4w9WgXcQ', API_KEY)
print(f"Titolo: {metadata['title']}")
print(f"Canale: {metadata['channel_title']}")
print(f"Visualizzazioni: {metadata['view_count']:,}")
print(f"Tag: {', '.join(metadata['tags'][:5])}")

Determinazione della rilevanza dei contenuti

Per argomenti tecnici è importante la freschezza delle informazioni. Aggiungiamo una funzione per valutare la rilevanza:

from datetime import datetime, timedelta

def calculate_content_freshness(published_date_str):
    """Valutazione della rilevanza dei contenuti"""
    published_date = datetime.fromisoformat(published_date_str.replace('Z', '+00:00'))
    age_days = (datetime.now(published_date.tzinfo) - published_date).days
    
    if age_days < 30:
        return 'very_fresh'
    elif age_days < 180:
        return 'fresh'
    elif age_days < 365:
        return 'moderate'
    else:
        return 'old'

def calculate_quality_score(metadata):
    """Calcolo del punteggio di qualità della fonte"""
    score = 0
    
    # Popolarità
    views = metadata['view_count']
    if views > 100000:
        score += 3
    elif views > 10000:
        score += 2
    elif views > 1000:
        score += 1
    
    # Engagement (like rispetto alle visualizzazioni)
    if views > 0:
        like_ratio = metadata['like_count'] / views
        if like_ratio > 0.05:
            score += 2
        elif like_ratio > 0.02:
            score += 1
    
    # Rilevanza
    freshness = calculate_content_freshness(metadata['published_at'])
    if freshness == 'very_fresh':
        score += 2
    elif freshness == 'fresh':
        score += 1
    
    return score

# Utilizzo
metadata = collect_video_metadata('dQw4w9WgXcQ', API_KEY)
quality = calculate_quality_score(metadata)
freshness = calculate_content_freshness(metadata['published_at'])
print(f"Punteggio di qualità: {quality}/7")
print(f"Rilevanza: {freshness}")

Parsing dei commenti per analisi contestuale

I commenti possono contenere informazioni preziose: correzioni di errori nel video, risorse aggiuntive, domande frequenti. Per i sistemi RAG questo è un contesto aggiuntivo.

def get_video_comments(video_id, api_key, max_results=100):
    """Ottenere commenti per il video"""
    url = 'https://www.googleapis.com/youtube/v3/commentThreads'
    comments = []
    next_page_token = None
    
    while len(comments) < max_results:
        params = {
            'part': 'snippet',
            'videoId': video_id,
            'maxResults': min(100, max_results - len(comments)),
            'order': 'relevance',  # Ordinamento per rilevanza
            'key': api_key
        }
        
        if next_page_token:
            params['pageToken'] = next_page_token
        
        response = requests.get(url, params=params)
        data = response.json()
        
        if 'items' not in data:
            break
        
        for item in data['items']:
            top_comment = item['snippet']['topLevelComment']['snippet']
            comments.append({
                'author': top_comment['authorDisplayName'],
                'text': top_comment['textDisplay'],
                'like_count': top_comment['likeCount'],
                'published_at': top_comment['publishedAt'],
                'reply_count': item['snippet']['totalReplyCount']
            })
        
        next_page_token = data.get('nextPageToken')
        if not next_page_token:
            break
    
    return comments

def filter_valuable_comments(comments, min_likes=5):
    """Filtrare commenti preziosi"""
    valuable = []
    
    for comment in comments:
        # Criteri di valore:
        # 1. Molti like (popolarità)
        # 2. Ci sono risposte (ha suscitato discussione)
        # 3. Testo lungo (commento dettagliato)
        
        if (comment['like_count'] >= min_likes or 
            comment['reply_count'] > 0 or 
            len(comment['text']) > 200):
            valuable.append(comment)
    
    return valuable

# Utilizzo
comments = get_video_comments('dQw4w9WgXcQ', API_KEY, max_results=50)
valuable_comments = filter_valuable_comments(comments)

print(f"Totale commenti: {len(comments)}")
print(f"Commenti preziosi: {len(valuable_comments)}")

for comment in valuable_comments[:3]:
    print(f"\n[{comment['like_count']} like] {comment['author']}:")
    print(comment['text'][:200])

Utilizzo di proxy per scalare la raccolta di dati

Durante la raccolta massiva di dati sorgono due problemi: i limiti dell'API di YouTube (10.000 quote al giorno) e i blocchi durante il parsing dei sottotitoli. I proxy aiutano a risolvere entrambi i problemi.

Quando sono necessari i proxy per il parsing di YouTube

  • Superamento delle quote API — utilizzando più chiavi API tramite diversi IP, è possibile aumentare il limite giornaliero
  • Parsing dei sottotitoli bypassando l'API — la libreria youtube-transcript-api effettua richieste dirette, che possono essere bloccate ad alta frequenza
  • Raccolta di dati da diverse regioni — alcuni video sono disponibili solo in determinati paesi
  • Raccolta parallela — distribuzione del carico su più IP per accelerare il processo

Scelta del tipo di proxy

Tipo di proxy Vantaggi Quando utilizzare
Data-center Alta velocità, basso costo Lavoro con API, piccoli volumi
Residenziali Basso rischio di blocchi, IP reali Parsing massivo dei sottotitoli, bypassare le restrizioni
Mobile Massimo affidamento, rari blocchi Raccolta di dati da applicazioni mobili, compiti critici

Per la maggior parte delle attività, i sistemi RAG si adattano a proxy residenziali — offrono un equilibrio tra costo e affidabilità durante il parsing massivo.

Configurazione dei proxy nel codice

import requests
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api._api import TranscriptListFetcher

# Configurazione del proxy
PROXY = {
    'http': 'http://username:password@proxy-server:port',
    'https': 'http://username:password@proxy-server:port'
}

# Per lavorare con l'API tramite proxy
def get_video_details_with_proxy(video_id, api_key, proxy):
    url = f'https://www.googleapis.com/youtube/v3/videos'
    params = {
        'part': 'snippet,statistics',
        'id': video_id,
        'key': api_key
    }
    
    response = requests.get(url, params=params, proxies=proxy, timeout=10)
    return response.json()

# Per il parsing dei sottotitoli tramite proxy
class ProxiedTranscriptApi:
    def __init__(self, proxy):
        self.proxy = proxy
    
    def get_transcript(self, video_id, languages=['en']):
        # Creiamo una sessione personalizzata con il proxy
        session = requests.Session()
        session.proxies = self.proxy
        
        # Utilizziamo la sessione per le richieste
        fetcher = TranscriptListFetcher(session)
        transcript_list = fetcher.fetch(video_id)
        
        # Otteniamo la lingua desiderata
        for lang in languages:
            try:
                transcript = transcript_list.find_transcript([lang])
                return transcript.fetch()
            except:
                continue
        
        raise Exception(f"Sottotitoli non trovati per le lingue: {languages}")

# Utilizzo
api = ProxiedTranscriptApi(PROXY)
transcript = api.get_transcript('dQw4w9WgXcQ', languages=['ru', 'en'])
print(f"Ottenuti {len(transcript)} segmenti di sottotitoli")

Rotazione dei proxy per scalare

Durante la raccolta di dati da migliaia di video è importante distribuire il carico tra diversi proxy:

import random
import time

class ProxyRotator:
    def __init__(self, proxy_list):
        self.proxies = proxy_list
        self.current_index = 0
    
    def get_next_proxy(self):
        """Rotazione sequenziale"""
        proxy = self.proxies[self.current_index]
        self.current_index = (self.current_index + 1) % len(self.proxies)
        return proxy
    
    def get_random_proxy(self):
        """Rotazione casuale"""
        return random.choice(self.proxies)

# Elenco dei proxy
PROXY_LIST = [
    {'http': 'http://user:pass@proxy1:port', 'https': 'http://user:pass@proxy1:port'},
    {'http': 'http://user:pass@proxy2:port', 'https': 'http://user:pass@proxy2:port'},
    {'http': 'http://user:pass@proxy3:port', 'https': 'http://user:pass@proxy3:port'},
]

rotator = ProxyRotator(PROXY_LIST)

def collect_data_with_rotation(video_ids):
    results = []
    
    for video_id in video_ids:
        proxy = rotator.get_next_proxy()
        
        try:
            # Ottenere metadati
            metadata = get_video_details_with_proxy(video_id, API_KEY, proxy)
            
            # Ottenere sottotitoli
            api = ProxiedTranscriptApi(proxy)
            transcript = api.get_transcript(video_id)
            
            results.append({
                'video_id': video_id,
                'metadata': metadata,
                'transcript': transcript
            })
            
            # Ritardo tra le richieste
            time.sleep(1)
            
        except Exception as e:
            print(f"Errore per {video_id}: {e}")
            continue
    
    return results

# Utilizzo
video_ids = ['video1', 'video2', 'video3', 'video4', 'video5']
data = collect_data_with_rotation(video_ids)
print(f"Dati raccolti per {len(data)} video")

Elaborazione e preparazione dei dati per RAG

Dopo aver raccolto i dati, è necessario elaborarli e strutturarli per un funzionamento efficace dei sistemi RAG.

Creazione di embedding vettoriali

I sistemi RAG utilizzano la ricerca vettoriale per trovare frammenti rilevanti. È necessario convertire il testo in embedding:

from sentence_transformers import SentenceTransformer
import numpy as np

# Caricamento del modello per la creazione di embedding
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')

def create_embeddings_from_transcript(transcript_chunks):
    """Creazione di embedding per chunk di sottotitoli"""
    embeddings = []
    
    for chunk in transcript_chunks:
        # Combiniamo il testo con i metadati per un miglior contesto
        text_with_context = f"{chunk['title']} | {chunk['text']}"
        
        # Creiamo l'embedding
        embedding = model.encode(text_with_context)
        
        embeddings.append({
            'video_id': chunk['video_id'],
            'timestamp': chunk['timestamp'],
            'text': chunk['text'],
            'embedding': embedding.tolist(),
            'metadata': {
                'title': chunk['title'],
                'channel': chunk['channel'],
                'views': chunk['views']
            }
        })
    
    return embeddings

# Preparazione dei dati
def prepare_rag_data(video_data):
    """Preparazione di tutti i dati per RAG"""
    all_chunks = []
    
    for video in video_data:
        metadata = video['metadata']
        transcript = video['transcript']
        
        # Divisione dei sottotitoli in chunk
        chunks = create_chunks_with_timestamps(transcript)
        
        # Aggiunta di metadati a ogni chunk
        for chunk in chunks:
            chunk['title'] = metadata['title']
            chunk['channel'] = metadata['channel_title']
            chunk['views'] = metadata['view_count']
            all_chunks.append(chunk)
    
    # Creazione di embedding
    embeddings = create_embeddings_from_transcript(all_chunks)
    
    return embeddings

# Utilizzo
rag_data = prepare_rag_data(collected_videos)
print(f"Preparati {len(rag_data)} frammenti per RAG")

Salvataggio in un database vettoriale

Per una ricerca efficace, gli embedding vengono salvati in database specializzati. Opzioni popolari: Pinecone, Weaviate, Qdrant, ChromaDB.

import chromadb
from chromadb.config import Settings

# Inizializzazione di ChromaDB (database vettoriale locale)
client = chromadb.Client(Settings(
    chroma_db_impl="duckdb+parquet",
    persist_directory="./youtube_rag_db"
))

# Creazione della collezione
collection = client.create_collection(
    name="youtube_transcripts",
    metadata={"description": "Trascrizioni video di YouTube per RAG"}
)

def store_in_vector_db(embeddings_data, collection):
    """Salvataggio degli embedding nel database vettoriale"""
    
    ids = []
    embeddings = []
    documents = []
    metadatas = []
    
    for i, item in enumerate(embeddings_data):
        ids.append(f"{item['video_id']}_{i}")
        embeddings.append(item['embedding'])
        documents.append(item['text'])
        metadatas.append({
            'video_id': item['video_id'],
            'timestamp': item['timestamp'],
            'title': item['metadata']['title'],
            'channel': item['metadata']['channel'],
            'views': str(item['metadata']['views']),
            'youtube_url': f"https://youtube.com/watch?v={item['video_id']}&t={int(float(item['timestamp'].split(':')[0])*60 + float(item['timestamp'].split(':')[1]))}s"
        })
    
    # Aggiunta alla collezione
    collection.add(
        ids=ids,
        embeddings=embeddings,
        documents=documents,
        metadatas=metadatas
    )
    
    print(f"Salvati {len(ids)} embedding nel database vettoriale")

# Utilizzo
store_in_vector_db(rag_data, collection)

Ricerca e generazione di risposte

L'ultimo passo è implementare la ricerca RAG e la generazione di risposte:

def search_youtube_knowledge(query, collection, model, top_k=3):
    """Ricerca di frammenti rilevanti da YouTube"""
    
    # Creiamo l'embedding della query
    query_embedding = model.encode(query).tolist()
    
    # Ricerca nel database vettoriale
    results = collection.query(
        query_embeddings=[query_embedding],
        n_results=top_k
    )
    
    # Formattazione dei risultati
    sources = []
    for i in range(len(results['ids'][0])):
        sources.append({
            'text': results['documents'][0][i],
            'metadata': results['metadatas'][0][i],
            'distance': results['distances'][0][i] if 'distances' in results else None
        })
    
    return sources

def generate_rag_answer(query, sources, llm_api_key):
    """Generazione di una risposta basata sulle fonti trovate"""
    
    # Formiamo il contesto dalle fonti trovate
    context = "\n\n".join([
        f"Fonte: {s['metadata']['title']} ({s['metadata']['timestamp']})\n{s['text']}"
        for s in sources
    ])
    
    # Prompt per LLM
    prompt = f"""Sulla base dei seguenti frammenti dai video di YouTube, rispondi alla domanda dell'utente.
Assicurati di citare le fonti con i timestamp.

Contesto:
{context}

Domanda: {query}

Risposta:"""
    
    # Qui chiama il tuo LLM (OpenAI, Claude, modello locale)
    # Esempio con OpenAI:
    # response = openai.ChatCompletion.create(
    #     model="gpt-4",
    #     messages=[{"role": "user", "content": prompt}]
    # )
    # answer = response.choices[0].message.content
    
    # Per esempio restituiamo il prompt
    return {
        'answer': 'Qui ci sarà la risposta LLM',
        'sources': sources
    }

# Utilizzo
query = "Come configurare un proxy in Python?"
sources = search_youtube_knowledge(query, collection, model, top_k=3)

print("Fonti trovate:")
for source in sources:
    print(f"\n{source['metadata']['title']}")
    print(f"Tempo: {source['metadata']['timestamp']}")
    print(f"Link: {source['metadata']['youtube_url']}")
    print(f"Testo: {source['text'][:200]}...")

Ottimizzazione della qualità RAG

Alcuni consigli per migliorare la qualità del sistema RAG sui dati di YouTube:

  • Filtra contenuti di bassa qualità — utilizza metriche di visualizzazioni, like, data di pubblicazione
  • Mantieni il contesto — aggiungi il titolo del video e del canale a ogni chunk di testo
  • Ottimizza la dimensione dei chunk — per contenuti tecnici, 300-500 parole è ottimale
  • Utilizza metadati per il ranking — contenuti più freschi e popolari possono avere la priorità
  • Aggiungi commenti — spesso contengono importanti chiarimenti e FAQ
  • Controlla la disponibilità dei video — alcuni video possono essere rimossi o diventare privati

Consiglio: Per la raccolta massiva di dati YouTube si consiglia di utilizzare una combinazione di API ufficiale (per metadati) e parsing tramite proxy (per sottotitoli). Questo consente di aggirare i limiti e ottenere il massimo delle informazioni.

Conclusione

La raccolta di dati YouTube per i sistemi RAG è un processo a più fasi che include lavoro con API, parsing di sottotitoli, elaborazione di metadati e creazione di embedding vettoriali. Punti chiave:

  • YouTube Data API v3 fornisce metadati, statistiche e commenti con un limite di 10.000 quote al giorno
  • I sottotitoli vengono parsati tramite la libreria youtube-transcript-api o richieste dirette
  • I timestamp sono fondamentali per creare collegamenti precisi alle fonti
  • I metadati (visualizzazioni, like, data) aiutano a valutare la qualità e la rilevanza dei contenuti
  • I commenti aggiungono contesto e spesso contengono FAQ
  • I proxy sono necessari per scalare e aggirare i limiti
  • Embedding vettoriali e database specializzati garantiscono una ricerca semantica rapida

Con una corretta configurazione del processo, è possibile raccogliere decine di migliaia di frammenti di contenuto di qualità al giorno, creando una potente base di conoscenza per i sistemi RAG in qualsiasi area tematica.

Se prevedi una raccolta massiva di dati YouTube con aggiramento di limiti e blocchi, ti consigliamo di utilizzare proxy residenziali — garantiscono stabilità durante il parsing di migliaia di video e minimizzano il rischio di blocchi da parte di YouTube.

```