Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
259 changes: 114 additions & 145 deletions README.md

Large diffs are not rendered by default.

11 changes: 2 additions & 9 deletions argos/captura.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,10 @@ class Corpus:
O mesmo texto chegando por outro id da mesma fonte (republicação) cai no mesmo
arquivo, e a referência gravada passa a ser a da captura mais recente. O relatório e
o JSONL da rodada guardam as duas.

Com `guardar=False` nada é gravado: a sentinela confere o documento em memória, a
triagem lê o texto e ele é descartado. É a escolha de quem quer só o catálogo (URL e
identificadores), ao preço de não poder retriar sem baixar de novo.
"""

def __init__(self, raiz: Path, guardar: bool = True) -> None:
def __init__(self, raiz: Path) -> None:
self.raiz = Path(raiz)
self.guardar = guardar

def relativo(self, caminho: Path | None) -> str | None:
"""Caminho como vai para a saída: relativo ao diretório de dados, portável."""
Expand All @@ -100,10 +95,8 @@ def relativo(self, caminho: Path | None) -> str | None:
def caminho(self, doc: Documento) -> Path:
return self.raiz / nome_seguro(doc.ref.fonte) / f"{doc.hash_texto}.json"

def gravar(self, doc: Documento, fonte: Fonte) -> tuple[bool, Path | None]:
def gravar(self, doc: Documento, fonte: Fonte) -> tuple[bool, Path]:
"""(íntegro, caminho). Grava `.part`, pergunta à sentinela, promove se passar."""
if not self.guardar:
return fonte.sentinela(doc), None
final = self.caminho(doc)
final.parent.mkdir(parents=True, exist_ok=True)
parcial = final.with_suffix(".json.part")
Expand Down
38 changes: 1 addition & 37 deletions argos/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
python -m argos rodar --config exemplos/config.exemplo.json
python -m argos rodar --config ... --desde 2026-09-01 --sem-estado
python -m argos retriar --config ...
python -m argos estimar --config ...
python -m argos validar-lexico exemplos/lexico.exemplo.json

Saídas: 0 nada a ler; 2 erro de execução ou fonte fora do ar; 3 há itens que pedem juízo.
Expand All @@ -16,8 +15,7 @@
import sys
from datetime import date

from argos import __version__, config, estimativa, fontes, lexico, rodada, saidas
from argos.saidas import catalogo
from argos import __version__, config, fontes, lexico, rodada, saidas


def _rodar(args: argparse.Namespace) -> int:
Expand All @@ -32,46 +30,18 @@ def _rodar(args: argparse.Namespace) -> int:
resultado = rodada.rodar(cfg, instancias, casador, desde=desde, usar_estado=not args.sem_estado)
pasta = saidas.escrever(resultado, cfg.saidas)
print(f"{len(resultado.linhas)} itens; saídas em {pasta}")
_catalogar(cfg, resultado)
return resultado.codigo_saida


def _catalogar(cfg: config.Config, resultado: rodada.Rodada) -> None:
if cfg.catalogo_csv is None:
return
nivel = int(cfg.catalogo.get("nivel_minimo", 2))
novas = catalogo.atualizar(resultado, cfg.catalogo_csv, nivel)
print(f"catálogo: {novas} URLs novas em {cfg.catalogo_csv}")


def _retriar(args: argparse.Namespace) -> int:
cfg = config.carregar(args.config)
casador = lexico.Casador(lexico.carregar(cfg.lexico))
resultado = rodada.retriar(cfg, casador, args.fonte)
pasta = saidas.escrever(resultado, cfg.saidas)
print(f"{len(resultado.linhas)} itens retriados; saídas em {pasta}")
_catalogar(cfg, resultado)
return resultado.codigo_saida


def _estimar(args: argparse.Namespace) -> int:
cfg = config.carregar(args.config)
estratos = {f["id"]: f.get("estrato", "geral") for f in cfg.fontes}
desde = date.fromisoformat(args.desde) if args.desde else None
por_estrato = estimativa.calcular(
cfg.saidas, args.nivel_minimo, lambda fonte: estratos.get(fonte, "geral"), desde
)
texto = estimativa.relatorio(por_estrato, desde)
destino = cfg.diretorio / "estimativa.md"
destino.parent.mkdir(parents=True, exist_ok=True)
destino.write_text(texto, encoding="utf-8")
for nome, est in sorted(por_estrato.items()):
piso = f"{est.chao:,.0f}" if est.chao is not None else "sem estimativa (um canal só)"
print(f"{nome}: {len(est.observadas)} URLs observadas; piso estimado: {piso}")
print(f"relatório em {destino}")
return rodada.SEM_NADA


def _validar_lexico(args: argparse.Namespace) -> int:
try:
lex = lexico.carregar(args.arquivo)
Expand Down Expand Up @@ -101,12 +71,6 @@ def main(argv: list[str] | None = None) -> int:
p.add_argument("--fonte")
p.set_defaults(func=_retriar)

p = sub.add_parser("estimar", help="quanto falta: captura e recaptura entre os canais")
p.add_argument("--config", required=True)
p.add_argument("--nivel-minimo", type=int, default=2)
p.add_argument("--desde", help="AAAA-MM-DD: só itens a partir desta data")
p.set_defaults(func=_estimar)

p = sub.add_parser("validar-lexico", help="confere o formato de um léxico")
p.add_argument("arquivo")
p.set_defaults(func=_validar_lexico)
Expand Down
14 changes: 0 additions & 14 deletions argos/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
"diretorio": "dados",
"desde": "2026-09-01",
"margem_dias": 2,
"guardar_texto": true,
"catalogo": {"arquivo": "catalogo.csv", "nivel_minimo": 2},
"fontes": [{"tipo": "rss", "id": "rss:exemplo", "url": "https://..."}]
}

Expand All @@ -31,16 +29,6 @@ class Config:
# Quanto voltar antes da última rodada: fonte que publica com atraso ou com data
# retroativa não escapa. O estado impede a releitura do que já foi visto.
margem_dias: int = 2
# False: o texto integral é lido, triado e descartado; nada vai para `corpus/`.
guardar_texto: bool = True
# {"arquivo": "catalogo.csv", "nivel_minimo": 2}: mantém o catálogo CSV cumulativo.
catalogo: dict | None = None

@property
def catalogo_csv(self) -> Path | None:
if not self.catalogo:
return None
return self.diretorio / self.catalogo.get("arquivo", "catalogo.csv")

@property
def estado(self) -> Path:
Expand Down Expand Up @@ -71,6 +59,4 @@ def carregar(caminho: str | Path) -> Config:
fontes=tuple(fontes),
desde=date.fromisoformat(dados["desde"]) if dados.get("desde") else None,
margem_dias=int(dados.get("margem_dias", 2)),
guardar_texto=bool(dados.get("guardar_texto", True)),
catalogo=dados.get("catalogo"),
)
216 changes: 0 additions & 216 deletions argos/estimativa.py

This file was deleted.

6 changes: 0 additions & 6 deletions argos/fontes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,15 @@
from argos.contrato import Fonte
from argos.fontes.datajud import DataJud
from argos.fontes.djen import Djen
from argos.fontes.gdelt import Gdelt
from argos.fontes.lista import Lista
from argos.fontes.openalex import OpenAlex
from argos.fontes.rss import Rss
from argos.fontes.wayback import Wayback
from argos.http import Transporte, transporte_urllib

TIPOS = {
"rss": Rss,
"datajud": DataJud,
"djen": Djen,
"lista": Lista,
"wayback": Wayback,
"openalex": OpenAlex,
"gdelt": Gdelt,
}


Expand Down
Loading
Loading