b45bc9bbad
- app.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
74 lines
3.5 KiB
Markdown
74 lines
3.5 KiB
Markdown
---
|
|
name: gnula_grabber
|
|
lang: py
|
|
domain: infra
|
|
version: 0.1.0
|
|
description: "Pipeline 2-partes: detecta pelis en castellano en gnula (crawler→catálogo SQLite) y las descarga via Chrome+CDP+NordVPN (HLS streaming+descifrado AES) → manual/movies → Radarr/Jellyfin. Captcha=humano."
|
|
tags: [gnula, hls, scraping, cdp, nordvpn, media, popelis, navegator]
|
|
uses_functions:
|
|
- extract_hls_from_cdp_tab_py_pipelines
|
|
- start_nordvpn_socks_bridge_bash_infra
|
|
- popelis_import_media_drop_py_infra
|
|
- chrome_load_extensions_bash_browser
|
|
uses_types: []
|
|
framework: ""
|
|
entry_point: "crawl.py"
|
|
dir_path: "apps/gnula_grabber"
|
|
repo_url: ""
|
|
---
|
|
|
|
## Propósito
|
|
|
|
Sistema 2-partes para poblar la biblioteca Jellyfin con pelis en **castellano** desde gnula
|
|
(gnularetro.cc), saltando el bloqueo del ISP (DPI Allot, vía NordVPN) y Cloudflare (navegador real).
|
|
|
|
## Parte 1 — Detector (`crawl.py`)
|
|
Crawler vía **FlareSolverr** (Chrome headless NordVPN+CF). Recorre listados/categorías,
|
|
parsea `<article class="item movies">`, filtra los que tienen bandera **es.png** (= "Español"
|
|
dentro de la página; el alt-text del listado está invertido — usar el nombre de imagen),
|
|
dedup vs catálogo + Radarr, y guarda en SQLite `~/.config/popelis/gnula_catalog.db`
|
|
(tabla `movies`: href, title, year, flags, lang_es, status, in_library).
|
|
```bash
|
|
python3 apps/gnula_grabber/crawl.py "peliculas/estrenos" 2
|
|
python3 apps/gnula_grabber/crawl.py "peliculas/accion" 2 # paginación rota -> recorrer categorías
|
|
```
|
|
|
|
## Parte 2 — Downloader (`download.py`)
|
|
Consume el catálogo (pelis `status=pending`). Por cada una: navega a su página en el Chrome
|
|
CDP, clica el server **Español** (luluvid/luluvdo, `li[data-nume]` del grupo es.png), quita el
|
|
overlay de ad (`div z-index>=1000`) + `jwplayer().play()` + trusted click, espera `master.m3u8`
|
|
(captcha=humano), y delega a `grab_stream.py`. Marca `downloaded`.
|
|
```bash
|
|
python3 apps/gnula_grabber/download.py 1 # baja 1 peli pending
|
|
```
|
|
|
|
## Núcleo — `grab_stream.py`
|
|
Descarga HLS **streaming a disco** (no blob → no peta Chrome): in-page fetchea cada segmento
|
|
crudo (sesión browser = pasa el 522 CF), lo manda por CDP, y LOCAL descifra AES-128-CBC
|
|
(key+IV de `#EXT-X-KEY`; IV=media-sequence) + append a `.ts` + remux `ffmpeg -c copy` → `.mkv`
|
|
directo a `F:\POPELIS\manual\movies`. El timer systemd `popelis-import.timer` lo importa
|
|
(metadata Radarr) → `media` → Jellyfin (realtime monitor).
|
|
```bash
|
|
python3 apps/gnula_grabber/grab_stream.py "Titulo (2025)" # con el player luluvdo reproduciendo
|
|
```
|
|
|
|
## Prerequisitos
|
|
- Bridge NordVPN (`start_nordvpn_socks_bridge --port 8889`).
|
|
- gluetun+FlareSolverr arriba (para el crawler).
|
|
- Chrome CDP+NordVPN con perfil **`gnula_popelis`** (cookies de gnula/luluvdo + uBlock
|
|
Origin Lite ya instalado vía Web Store — persiste en el perfil, no se pasan flags de ext;
|
|
`--load-extension` está MUERTO en Chrome stable 148, ver `chrome_load_extensions_bash_browser`):
|
|
```bash
|
|
CHROME="/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"
|
|
setsid "$CHROME" --remote-debugging-port=9222 --remote-debugging-address=0.0.0.0 \
|
|
'--remote-allow-origins=*' \
|
|
'--user-data-dir=C:\Users\lucas\AppData\Local\gnula_popelis' \
|
|
--proxy-server=http://127.0.0.1:8889 --no-first-run --no-default-browser-check \
|
|
'https://www.gnularetro.cc/' </dev/null >/tmp/chrome_gnula.log 2>&1 &
|
|
```
|
|
- venv con `pycryptodome` + `websocket-client` (vía `uv run --with`).
|
|
|
|
## Gotchas
|
|
- Ver `README.md` para el flujo completo + gotchas (overlay ad, --load-extension Chrome 148,
|
|
token efímero, 522 solo-externos, paginación gnula rota → categorías).
|