#!/usr/bin/env python3 """ยง3.5 del plan: deriva `site/` a partir de `raw/` (que queda intacto). - Reescribe los enlaces absolutos a `antiguo.feadulta.com` como raiz-relativos, para que el mirror funcione bajo cualquier hostname (p.ej. legacy.rafacalvo.nyc). - Deja intactos los enlaces externos (incluido www.feadulta.com, que ahora es WordPress). - Neutraliza los formularios que apuntan a endpoints PHP vivos: quedan inertes y con aviso. - Descarta las vistas de impresion (`?tmpl=component&print=1`), que duplican paginas ya capturadas. - Deja una copia sin la query en el nombre para los ficheros que wget guardo como `app.js?hash` o `titulo?.html` (alias con '?' literal): un servidor estatico busca el nombre sin query. Uso: 45-normalize-links.py [--no-copy] (--no-copy reaprovecha el site/ existente) """ import os, re, json, shutil, sys from collections import Counter BASE = "/home/rafa/joomla-migration/mirror-antiguo" RUN = open(os.path.join(BASE, "CURRENT_RUN")).read().strip() DIR = os.path.join(BASE, "runs", RUN) RAW, SITE = os.path.join(DIR, "raw"), os.path.join(DIR, "site") HOSTABS = re.compile(rb'(?:https?:)?//antiguo\.feadulta\.com', re.I) FORM = re.compile(rb']*>', re.I) ACTION = re.compile(rb'action\s*=\s*["\']([^"\']*)["\']', re.I) AVISO = (b'
Archivo hist\xc3\xb3rico: este formulario no est\xc3\xa1 ' b'operativo.
') TEXTEXT = (".html", ".htm", ".css", ".js") def basename_sin_query(fn): """`app.js?hash` -> `app.js`; `titulo?.html` -> `titulo`. Sin '?' devuelve el propio nombre.""" return fn.split("?", 1)[0] def paso1_nombres_con_query(stats): """Se ejecuta ANTES de reescribir: descarta impresiones y crea las copias de nombre limpio.""" for root, _d, files in os.walk(SITE): for fn in list(files): if "?" not in fn: continue src = os.path.join(root, fn) if "print=1" in fn: os.remove(src) stats["vistas_impresion_descartadas"] += 1 continue base = basename_sin_query(fn) if not base: continue dst = os.path.join(root, base) if not os.path.exists(dst): shutil.copy2(src, dst) stats["copias_con_nombre_limpio"] += 1 def paso2_reescribe(stats): for root, _d, files in os.walk(SITE): for fn in files: # la extension se mira sobre el nombre SIN query: `x.html?foo` sigue siendo HTML base = basename_sin_query(fn).lower() if not base.endswith(TEXTEXT): continue p = os.path.join(root, fn) try: data = open(p, "rb").read() except OSError: continue orig = data data, n = HOSTABS.subn(b"", data) stats["enlaces_absolutos_reescritos"] += n if base.endswith((".html", ".htm")): def fix_form(m): tag = m.group(0) a = ACTION.search(tag) if a and b".php" in a.group(1): stats["formularios_neutralizados"] += 1 return ACTION.sub(b'action="#" onsubmit="return false"', tag) + AVISO return tag data = FORM.sub(fix_form, data) if data != orig: open(p, "wb").write(data) stats["ficheros_modificados"] += 1 def main(): if "--no-copy" not in sys.argv: if os.path.exists(SITE): print("site/ ya existe, lo borro"); shutil.rmtree(SITE) print("copiando raw/ -> site/ ...") shutil.copytree(RAW, SITE) else: print("reaprovechando site/ existente") stats = Counter() paso1_nombres_con_query(stats) paso2_reescribe(stats) out = os.path.join(DIR, "link-rewrite.json") json.dump(dict(stats), open(out, "w"), indent=2, ensure_ascii=False) print(json.dumps(dict(stats), indent=2, ensure_ascii=False)) print("informe:", out) if __name__ == "__main__": main()