Skip to content

feat(trf): download de peças via cpopg(download_pecas=True) para TRF1/3/5 (#272)#274

Open
jtrecenti wants to merge 3 commits into
mainfrom
feat/trf3-download-pecas-iss272
Open

feat(trf): download de peças via cpopg(download_pecas=True) para TRF1/3/5 (#272)#274
jtrecenti wants to merge 3 commits into
mainfrom
feat/trf3-download-pecas-iss272

Conversation

@jtrecenti
Copy link
Copy Markdown
Owner

Summary

  • Novo parâmetro download_pecas: bool = False (+ diretorio) em cpopg de TRF1, TRF3 e TRF5. Quando True, baixa cada peça (documento juntado) via documentoSemLoginHTML.seam para <diretorio>/<cnj>/<id_processo_doc>.html e adiciona coluna pecas ao DataFrame com a lista de caminhos por processo.
  • Default False preserva o comportamento atual (só metadados + movs + lista de documentos).
  • A flag fica no cpopg (e não num método separado) porque os tokens ca que identificam cada peça estão amarrados à conversa Seam do detalhe — peças precisam ser baixadas na mesma requests.Session. Folding na mesma chamada compartilha a session naturalmente e evita um GET duplicado do detalhe.
  • Bonus fix: cpopg agora pagina também a tabela processoDocumentoGridTab (Documentos juntados ao processo). Antes só paginava movs — processos com > 15 documentos só devolviam a primeira página na coluna documentos, e com download_pecas=True só as 15 primeiras peças eram baixadas. Verificado direto no sample detail_paginated.html (2 sliders Richfaces: um pra movs com 11 páginas, outro pra docs com 2). Nova função extract_docs_pagination espelha extract_movs_pagination (mesmo shape, mesma POST AJAX), e merge_docs_pages faz o splice no tbody correto.
  • Nova exceção juscraper.core.exceptions.BotChallengeBlockedError. Detecta o padrão 403 + body Access Denied + Reference Akamai e propaga em vez de virar warning silencioso por-item (é session-wide). Mensagem orienta a aguardar minutos ou trocar de IP (VPN/hotspot) e inclui a Reference Akamai. 403 sem Access Denied segue propagando como requests.HTTPError normal via raise_for_status.
  • Notebooks docs/notebooks/trf3.ipynb e trf5.ipynb documentam e demonstram a flag (célula nova executada ao vivo, output preservado).

Test plan

  • 42 contract tests (TRF1/3/5) verde — incluindo 3 novos para BotChallengeBlockedError e 3 novos para paginação de docs.
  • Integração test_cpopg_download_pecas_grava_arquivos (TRF3) baixou 4 peças de processo real.
  • Células dos notebooks trf3 e trf5 executadas ao vivo (output real preservado).
  • Pre-commit (ruff/isort/pylint/flake8/mypy) verde nos arquivos modificados.

Refs #272

jtrecenti added 3 commits May 24, 2026 07:26
Novo metodo `cpopg_download_pecas(id_cnj, diretorio=None)` que baixa as pecas
(documentos juntados) de cada processo via `documentoSemLoginHTML.seam`. Cada
peca vira `<diretorio>/<cnj>/<id_processo_doc>.html`, com o XHTML do viewer
auto-contido (imagens embarcadas como data: URLs).

O detalhe e refeito internamente em vez de receber a saida de `cpopg_download`
porque os tokens `ca` que identificam cada peca estao amarrados a conversa
Seam que renderizou o detalhe — peca tem que ser baixada na mesma
`requests.Session`. Encapsular detalhe + pecas no mesmo metodo evita expor
essa restricao na API publica (sessao expirada vira `login.seam` redirect).

Os tres TRFs PJe compartilham exatamente a mesma URL e parametros, mas a infra
foi duplicada por scraper (regra de memoria: evitar `_familia/` mesmo com 2+
ocorrencias). Apenas o `BASE_URL` muda; o resto e copia.
…ckedError

Mudanças sobre o commit anterior (5f52094):

- Remove `cpopg_download_pecas` separado e expõe a funcionalidade via
  `cpopg(id_cnj, download_pecas=False, diretorio=None)` nos 3 TRFs. Razão:
  a sessão é obrigatória para baixar as peças (tokens `ca` amarrados à
  conversa Seam do detalhe), então um método separado teria que refazer o
  GET do detalhe internamente para obter tokens válidos — desperdício.
  Junto na mesma chamada compartilha a session naturalmente.
  - Default `download_pecas=False`: comportamento atual de cpopg preservado.
  - Quando True, DataFrame ganha coluna `pecas` com lista de caminhos.
  - Schemas `InputCpopgTRF1/3/5` aceitam os 2 novos campos.

- Nova exceção `juscraper.core.exceptions.BotChallengeBlockedError`.
  Detecta o padrão 403 + "Access Denied" + Reference Akamai e propaga em
  vez de ser engolida pelos try/except por-item (é session-wide). Mensagem
  orienta a aguardar minutos ou trocar de IP (VPN/hotspot) e inclui a
  Reference Akamai. 403 sem Access Denied segue como `requests.HTTPError`.

- Notebooks `trf3.ipynb` e `trf5.ipynb` atualizados com a nova célula
  demonstrando `cpopg(..., download_pecas=True, diretorio=tmp)` e
  explicando por que a flag fica no cpopg (não num método separado).
A tabela `processoDocumentoGridTab` (Documentos juntados ao processo) usa
o mesmo widget Richfaces da tabela de movimentacoes — pagina em blocos de
15. Antes desse fix, processos com > 15 documentos so devolviam a primeira
pagina na coluna `documentos`, e com `download_pecas=True` so as 15
primeiras pecas eram baixadas.

`extract_docs_pagination` espelha `extract_movs_pagination` (mesmo shape de
`MovsPagination`, mesma POST AJAX via `fetch_movs_page`) mas alvo no
panel `processoDocumentoGridTabPanel`. `merge_docs_pages` faz o splice
no tbody correto sem mexer no de movs. `_fetch_one` paginas os dois
sliders em sequencia dentro da mesma sessao.

Refs #272.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant