3.9 KiB
3.9 KiB
CLI Contract & Routing Specification: scripts/extract_article_contents.py
1. Interface de Linha de Comando (CLI)
O script scripts/extract_article_contents.py preserva 100% da interface CLI existente sem novos argumentos:
python scripts/extract_article_contents.py \
-i, --input PATH # (Obrigatório) JSON de busca de notícias de entrada
[-o, --output PATH] # (Opcional) Caminho do JSON de saída textual
[-l, --limit N] # (Opcional) Limite máximo de artigos a processar
[--lang, --language CODE] # (Opcional) Código do idioma para NLP (ex: pt, es, en)
[-t, --timeout SEC] # (Opcional) Timeout em segundos para navegação (default: 30)
[-s, --silent] # (Opcional) Suprime logs no stderr
2. Regras de Resolução de Arquivos de Saída
Caso A: Sem -o/--output (Padrão)
Para uma entrada: out/river_plate.json
- Saída Textual:
out/river_plate_extracted.json - Saída de Mídia:
out/river_plate_media.json(gerado obrigatoriamente; contém{"articles": []}se nenhuma mídia for identificada)
Caso B: Com -o/--output customizado
Para uma entrada: out/noticias.json com -o out/processados/brasil_completo.json
- Saída Textual:
out/processados/brasil_completo.json - Saída de Mídia:
out/processados/brasil_completo_media.json(gerado obrigatoriamente; contém{"articles": []}se nenhuma mídia for identificada)
Regra:
- Diretório: mesmo diretório da saída textual informada.
- Nome base (stem): mesmo stem da saída textual informada.
- Sufixo:
_media. - Extensão:
.json. - Geração: O arquivo
*_media.jsonMUST ser gerado em toda execução bem-sucedida do lote, sem omissão condicional.
3. Estrutura do Arquivo de Saída Textual (*_extracted.json)
{
"source_file": "out/river_plate.json",
"processed_at": "2026-08-24T20:30:00.000000+00:00",
"total_articles": 8,
"successful_articles": 7,
"failed_articles": 1,
"articles": [
{
"input_meta": {
"titulo": "Notícia textual completa",
"url": "https://example.com/noticia-1",
"subtitulo": "Subtítulo",
"quando_publicado": "há 2 horas",
"pagina": 1
},
"extraction_status": "success",
"error_message": null,
"crawled_url": "https://example.com/noticia-1",
"page_title": "Título no DOM",
"http_status": 200,
"trafilatura": { "text": "...", "markdown": "...", "title": "..." },
"newspaper4k": { "text": "...", "summary": "...", "keywords": [] },
"readability": { "cleaned_text": "...", "cleaned_html": "..." }
},
{
"input_meta": {
"titulo": "Notícia onde todos provedores falharam",
"url": "https://example.com/falha"
},
"classification_status": "failed",
"error_message": "media classification providers unavailable",
"crawled_url": "https://example.com/falha",
"page_title": null,
"http_status": null,
"trafilatura": null,
"newspaper4k": null,
"readability": null
}
]
}
4. Estrutura do Arquivo de Saída de Mídia (*_media.json)
{
"articles": [
{
"input_meta": {
"titulo": "Vídeo dos melhores momentos do jogo",
"url": "https://example.com/video-gols",
"subtitulo": "Assista ao lance",
"quando_publicado": "há 1 hora",
"pagina": 1
},
"crawled_url": "https://example.com/video-gols",
"page_title": "Vídeo dos Melhores Momentos",
"http_status": 200,
"content_type": "media",
"media_type": "video"
}
]
}
5. Códigos de Saída (Exit Codes)
| Exit Code | Significado |
|---|---|
0 |
Lote processado com sucesso (arquivos gravados) |
1 |
Arquivo de entrada inexistente ou erro de argumentos CLI |
2 |
Erro fatal não tratado |
130 |
Interrupção pelo usuário (SIGINT / Ctrl+C) |