Lectii text: extract_text_lessons.py + Modul 3 #9 sumarizata
extract_audio.py sarea peste lectiile fara video. Gasita una in curriculum-ul accesibil (Modul 3 #9 - expirari de optiuni, witching, 0DTE), cu 4847 de caractere de continut real. Era numarata gresit ca acoperita. Plus: - render_html.py: index grupat pe module cu titlul H1 al fiecarei pagini - render_html.py: garda pe liniile goale din <svg> (rup blocul HTML tacut) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MtSTyTmt6AbCL9j5ajEDm1
This commit is contained in:
92
extract_text_lessons.py
Normal file
92
extract_text_lessons.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
Extrage lecțiile FĂRĂ video (text/quiz) — pe care extract_audio.py le sare,
|
||||
pentru că el caută doar un MP4.
|
||||
|
||||
API-ul de lecție întoarce conținutul în câmpul `html`, împreună cu tot
|
||||
CSS-ul paginii systeme.io. Curățăm style/script, apoi tagurile, și scriem
|
||||
text în același loc cu transcrierile, ca să intre în același flux de
|
||||
sumarizare.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import html as html_mod
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from download import BASE, get_course_id, get_lecture_video_url, get_menu, login, slugify
|
||||
from extract_audio import CORE_MODULES
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def lecture_text(session: requests.Session, lecture_id: int) -> str:
|
||||
raw = session.get(f"{BASE}/api/membership/lecture/{lecture_id}").json().get("html") or ""
|
||||
raw = re.sub(r"(?is)<(style|script)\b.*?</\1>", " ", raw)
|
||||
text = html_mod.unescape(re.sub(r"<[^>]+>", "\n", raw))
|
||||
lines = [ln.strip() for ln in text.split("\n") if ln.strip()]
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Extrage lecțiile text din cursul ATM")
|
||||
p.add_argument("--out", default="transcripts")
|
||||
p.add_argument("--only", default=None, help="Un singur modul (ocolește CORE_MODULES)")
|
||||
args = p.parse_args()
|
||||
|
||||
load_dotenv()
|
||||
email, password = os.getenv("ATM_EMAIL", ""), os.getenv("ATM_PASSWORD", "")
|
||||
if not email or not password:
|
||||
log.error("Setează ATM_EMAIL și ATM_PASSWORD în .env")
|
||||
sys.exit(1)
|
||||
|
||||
session = requests.Session()
|
||||
session.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"})
|
||||
login(session, email, password)
|
||||
modules = get_menu(session, get_course_id(session))
|
||||
|
||||
done = skipped = 0
|
||||
for mod_idx, mod in enumerate(modules, 1):
|
||||
if args.only:
|
||||
if mod["name"] != args.only:
|
||||
continue
|
||||
elif mod["name"] not in CORE_MODULES:
|
||||
continue
|
||||
|
||||
for lec_idx, lec in enumerate(mod["lectures"], 1):
|
||||
try:
|
||||
if get_lecture_video_url(session, lec["id"]):
|
||||
continue # are video -> îl ia extract_audio.py
|
||||
except requests.exceptions.HTTPError as e:
|
||||
if e.response is not None and e.response.status_code == 403:
|
||||
continue # fără acces
|
||||
raise
|
||||
|
||||
dest = Path(args.out) / f"{mod_idx:02d}_{slugify(mod['name'])}" / f"{lec_idx:02d}_{slugify(lec['name'])}.txt"
|
||||
if dest.exists() and dest.stat().st_size > 200:
|
||||
log.info(f" Există deja: {dest.name}")
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
text = lecture_text(session, lec["id"])
|
||||
if len(text) < 200:
|
||||
log.info(f" Prea puțin text, probabil quiz gol: {lec['name']}")
|
||||
continue
|
||||
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
dest.write_text(text, encoding="utf-8")
|
||||
log.info(f" Extras ({len(text)} caractere): {dest}")
|
||||
done += 1
|
||||
|
||||
log.info("=" * 60)
|
||||
log.info(f"Lecții text extrase: {done}, sărite: {skipped}.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user