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:
- Vai su console.cloud.google.com
- Crea un nuovo progetto o seleziona uno esistente
- Abilita YouTube Data API v3 nella sezione "APIs & Services"
- Crea credenziali (Credentials) → chiave API
- 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.