# yt-channel-scraper Scraper de canales de YouTube que extrae transcripciones, capítulos y metadatos completos, generando notas Markdown listas para Obsidian. Basado en la ingeniería inversa de [Obsidian Web Clipper](https://obsidian.md/) — usa `yt-dlp` internamente, que implementa el mismo mecanismo InnerTube (`youtubei/v1/player` con clientes ANDROID/IOS/WEB) que la extensión audita. ## Instalación ```bash cd yt-channel-scraper pip install -e ".[dev]" ``` Requiere Python ≥ 3.10. ## Uso ### Scrape completo de un canal ```bash yt-scraper --channel "https://www.youtube.com/@Nostal-Vlad/videos" ``` ### Dry run (ver qué descubriría sin descargar) ```bash yt-scraper --channel "https://www.youtube.com/@Nostal-Vlad/videos" --dry-run --limit 10 ``` ### Solo vídeos recientes ```bash yt-scraper --channel "https://www.youtube.com/@Nostal-Vlad/videos" --since 2025-01-01 ``` ### Reanudar tras interrupción ```bash yt-scraper --channel "https://www.youtube.com/@Nostal-Vlad/videos" ``` El estado se guarda en `data/state.db` (SQLite). Los vídeos ya procesados se saltan automáticamente. ### Reintentar vídeos con error ```bash yt-scraper --channel "https://www.youtube.com/@Nostal-Vlad/videos" --reset-errors ``` ## Opciones | Flag | Descripción | Default | |---|---|---| | `--channel, -c` | URL del canal | de config.yaml | | `--config` | Ruta al YAML de configuración | `config.yaml` | | `--limit N` | Procesar solo N vídeos | sin límite | | `--since DATE` | Solo vídeos desde YYYY-MM-DD | sin filtro | | `--languages, -l` | Idiomas preferidos (coma-sep) | `es,en` | | `--no-auto` | Ignorar subtítulos auto-generados | false | | `--no-shorts` | Excluir Shorts | de config | | `--include-shorts` | Incluir Shorts | de config | | `--resume/--no-resume` | Saltar procesados | `--resume` | | `--dry-run` | Solo discovery, no descargar | false | | `--reset-errors` | Reintentar vídeos con error | false | | `--verbose, -v` | Logging DEBUG | false | ## Configuración Copia `config.example.yaml` a `config.yaml` y edita: ```yaml channel_url: "https://www.youtube.com/@Nostal-Vlad/videos" languages: ["es", "es-419", "en"] prefer_manual: true include_shorts: false min_duration_sec: 30 delay: min_seconds: 1.5 max_seconds: 3.5 ``` ## Output Cada vídeo genera un archivo Markdown en `data/markdown/@canal/`: ``` data/markdown/Nostal Vlad/ ├── 2026-07-26_asi-era-ser-una-adolescente-edgy-en-los-2000.md ├── 2026-07-12_la-estetica-que-romantiza-ser-un-perdedor-losercore.md └── ... ``` Formato de cada nota: ```markdown --- video_id: gOUyxFwWQqA title: "La Estética Que ROMANTIZA ser un \"PERDEDOR\" | Losercore" channel: Nostal Vlad upload_date: 2026-07-12 duration: 1069 url: https://www.youtube.com/watch?v=gOUyxFwWQqA transcript_lang: es-orig transcript_src: auto views: 100523 likes: 8196 --- # La Estética Que ROMANTIZA ser un "PERDEDOR" | Losercore > [Ver en YouTube](https://www.youtube.com/watch?v=gOUyxFwWQqA) ## Transcripcion ### Intro (00:15) **00:15** · Una de las estéticas que ha cobrado más relevancia últimamente... **00:28** · que hacer esto. Y es que el loser core como tal es muy difuso... ### Losercore (01:38) **01:38** · ... ``` ## Estados en SQLite | Status | Significado | |---|---| | `pending` | Descubierto, sin procesar | | `done` | Transcripción extraída y Markdown generado | | `no_subtitles` | El vídeo no tiene subtítulos (ni manuales ni auto) | | `error` | Error al procesar (miembros-only, privado, bloqueo, etc.) | ## Arquitectura ``` cli.py Orquestador (Click + Rich progress) ├── discover.py yt-dlp --flat-playlist → lista de videoIds ├── store.py SQLite: estado, resume, dedup ├── extract.py yt-dlp.extract_info → metadata + subtítulos ├── parse.py JSON3/VTT → segmentos {start, end, text} ├── chapters.py align_chapters: capítulos ↔ segmentos ├── render.py Jinja2 → Markdown con frontmatter YAML └── ratelimit.py delays aleatorios + backoff exponencial ``` ## Tests ```bash python -m pytest tests/ -v ``` ## Mantenimiento Si la extracción falla tras una actualización de YouTube: ```bash yt-dlp -U # actualizar yt-dlp pip install -U yt-dlp ``` Las versiones de cliente InnerTube (ANDROID `20.10.x`, IOS `20.10.x`, WEB `2.2024xxxx`) rotan mensualmente. `yt-dlp` las mantiene actualizadas.