corrigido
USP virava 2 depositantes, EMBRAPA virava 5. Corrigido agrupando pela raiz do CNPJ (8 dígitos).
Pipeline de dados de patentes do INPI — depósito, publicação, despachos e anuidades — tratado e normalizado para responder perguntas de BI sobre tramitação processual. Recorte atual: pedidos depositados de 2010-01-01 até hoje, sem filtro de depositante ou IPC.
Testado antes de escrever qualquer pipeline: o que o portal de dados abertos cobre, e se a extranet permite automação.
Expandido em 2026-08-13 de "últimos 3 anos" pra 2010-01-01 até hoje (2010-01-01 a 2026-08-12), sem filtro de depositante ou IPC — 8,2x mais processos (56.329 → 461.159), quase 20x mais despachos (128.077 → 2.515.946), já que processos mais antigos tiveram mais tempo de acumular despacho.
Reescrito via Selenium replicando o fluxo de clique real (busca → resultado → modal de anuidades) — a causa do "endpoint vazio" nunca foi bot detection, era o servidor só liberar o detalhe depois da busca ser submetida naquela sessão. Lote de validação em escala: 499/500 processos, 1 erro (99,8%), ~4h19min headless, sem degradação ao longo do lote.
CodPedido é o codigo_interno dos dados abertos, mas numero_pedido (o que se digita na busca) é outro campo — precisa dos dois.Download dos 9 CSVs de dados abertos (~1,9 GB), filtro pelo recorte via semi-join por codigo_interno, montagem do modelo estrela.
Depositante resolvido por raiz de CNPJ (8 dígitos, agrupa filiais) quando disponível; senão por nome normalizado (acento + pontuação removidos).
dim_processo, dim_depositante, fato_processo_depositante, fato_despacho e agora fato_anuidade (166 processos) prontos em data/gold/, mais um banco DuckDB persistente (inpi.duckdb) com views e macros parametrizadas.
Docker Desktop instalado (via winget, sem reiniciar), Airflow 3.3.1 rodando via docker-compose com LocalExecutor. DAG completo (download → bronze → silver → gold → validate) testado ao vivo — passou ponta a ponta em ~16s.
Dois painéis calculam ao vivo: "tempo entre despacho X e Y" (com filtro opcional de depositante) e "quantos casos do depositante F tiveram despacho Z na janela T" — pra qualquer código/nome/data. Reescrito pra DuckDB-WASM (SQL de verdade, rodando no navegador) depois que a expansão do recorte pra 2010+ estourou o limite de embutir os dados brutos na página (2,5 milhões de despachos = 60MB de JSON). Dados em parquet comprimido (~13MB) servidos separado do HTML.
USP virava 2 depositantes, EMBRAPA virava 5. Corrigido agrupando pela raiz do CNPJ (8 dígitos).
8.873 empresas estrangeiras diferentes colapsaram num único depositante fictício de 29 mil processos. Corrigido: só dígitos puros contam como identificador.
INSERM (instituto francês) aparecia como 3 depositantes por variação de encoding no nome. Corrigido com normalização de acento e pontuação.
WHERE NOT sigiloso filtrava a tabela inteira — NULL não é TRUE em SQL de três valores. Corrigido com coalesce(..., false).
As views de tempo/contagem agrupam por depositante — somar qtd_processos pra achar um total geral conta processos com múltiplos depositantes várias vezes. 7.1→9.2 tinha sido reportado como 1.284 processos; o real (por codigo_interno) é 282. Corrigido com macros que contam por processo.
Testado requests, Playwright (headless/headed/anti-detecção) e undetected-chromedriver — todos vazios. Causa real: o servidor só libera Action=detail depois da busca ser submetida naquela sessão. Resolvido replicando o fluxo de clique completo via Selenium comum.
Expandir o recorte pra 2010+ (2,5 milhões de despachos) estourou o limite de 16MB do artifact (JSON bruto viraria 60MB). DuckDB-WASM resolveria, mas o binário sozinho (34-41MB) passa até do limite de 25MB por arquivo do Cloudflare Pages. Solução: motor via jsDelivr (CDN pública do próprio pacote npm — a recomendação padrão da lib), só os dados (parquet comprimido, ~13MB) hospedados no Pages.
500 de 461.159 (0,1%) até agora, ritmo confiável (~22-30s/processo, 99,8% de sucesso no último lote de 500). Coleta contínua de longo prazo, não uma meta de curto prazo — o recorte cresceu 8x com a expansão pra 2010+.
13 de 606 registros (2,1%) vieram com status "Tipo: Anuidade" em vez do status real — bug pontual de parsing a rastrear em process_detail.py.
Agora em inpi-patent-tracker.pages.dev com DuckDB-WASM (SQL de verdade, recorte completo de 2010+). O artifact do claude.ai continua existindo mas não acompanha mais essa versão pesada — 89MB não cabe no limite de 16MB. Considerar Metabase de verdade se as perguntas ad-hoc crescerem além do que os dois painéis cobrem.