Captura integral do acervo da Brasiliana Fotográfica (Biblioteca Nacional) para s3://brasiliana: 13.060 itens, 12.985 com imagem de preservação, 13.059 com miniatura derivada, 2.137 cópias legadas e 636 posts do blog. 41.444 objetos no ledger. Os 75 itens sem preservação estão em errors.md: a página do item responde 200, mas a origem serve o bitstream com HTTP 500. Nenhum fica fora do mural, porque todos têm thumbnail. Não versionado, por viver no bucket ou ser reconstruível: catálogo, posts .jsonl, atlas .webp, sqlite de estado e logs. Credenciais ficam de fora pelo .gitignore.
76 lines
2.5 KiB
Python
76 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Converte wordpress-posts.jsonl (saido do coletor-wordpress.js) em um .md
|
|
por post, com front-matter YAML. Imagens NAO sao baixadas -- os posts so
|
|
usam miniaturas dos mesmos handles que o acervo principal ja cobre (ver
|
|
PLANO.md); o valor novo aqui e o texto + o mapeamento pra handles.
|
|
|
|
Uso: python3 converte-wordpress-md.py [wordpress-posts.jsonl] [pasta-saida]
|
|
"""
|
|
import json, re, sys, unicodedata
|
|
from pathlib import Path
|
|
|
|
ENTRADA = Path(sys.argv[1] if len(sys.argv) > 1 else "wordpress-posts.jsonl")
|
|
SAIDA = Path(sys.argv[2] if len(sys.argv) > 2 else "../wordpress")
|
|
SAIDA.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
def slug(txt):
|
|
txt = unicodedata.normalize("NFKD", txt).encode("ascii", "ignore").decode()
|
|
txt = re.sub(r"[^a-zA-Z0-9]+", "-", txt).strip("-").lower()
|
|
return txt[:80] or "sem-titulo"
|
|
|
|
|
|
def yaml_str(s):
|
|
if s is None:
|
|
return "null"
|
|
return '"' + str(s).replace("\\", "\\\\").replace('"', '\\"') + '"'
|
|
|
|
|
|
def yaml_lista(items):
|
|
if not items:
|
|
return "[]"
|
|
return "[" + ", ".join(yaml_str(i) for i in items) + "]"
|
|
|
|
|
|
n_ok = n_erro = 0
|
|
for linha in open(ENTRADA, encoding="utf-8"):
|
|
if not linha.strip():
|
|
continue
|
|
post = json.loads(linha)
|
|
if post.get("erro"):
|
|
n_erro += 1
|
|
continue
|
|
|
|
titulo = post.get("titulo") or f"post-{post['id']}"
|
|
nome_arquivo = f"{post['id']}-{slug(titulo)}.md"
|
|
|
|
frontmatter = "\n".join([
|
|
"---",
|
|
f"id: {post['id']}",
|
|
f"url: {yaml_str(post.get('url'))}",
|
|
f"titulo: {yaml_str(titulo)}",
|
|
f"autor: {yaml_str(post.get('autor'))}",
|
|
f"data: {yaml_str(post.get('data_iso'))}",
|
|
f"categorias: {yaml_lista(post.get('categorias') or [])}",
|
|
f"handles_referenciados: {yaml_lista(post.get('handles_referenciados') or [])}",
|
|
f"fetched_at: {yaml_str(post.get('fetched_at'))}",
|
|
"---",
|
|
])
|
|
|
|
corpo = post.get("corpo") or "*(sem conteúdo extraído)*"
|
|
|
|
# nota de referencia pros handles, com link relativo pro nosso acervo
|
|
handles = post.get("handles_referenciados") or []
|
|
nota_handles = ""
|
|
if handles:
|
|
linhas_h = "\n".join(f"- `{h}` — `itens/{h.replace('/', '_')}/`" for h in handles)
|
|
nota_handles = f"\n\n---\n\n**Itens do acervo referenciados neste post:**\n\n{linhas_h}\n"
|
|
|
|
conteudo = f"{frontmatter}\n\n# {titulo}\n\n{corpo}{nota_handles}\n"
|
|
(SAIDA / nome_arquivo).write_text(conteudo, encoding="utf-8")
|
|
n_ok += 1
|
|
|
|
print(f"{n_ok} arquivos .md gerados em {SAIDA.resolve()}")
|
|
print(f"{n_erro} posts com erro na coleta, pulados")
|