# 🤖 Automação NFSe – Prefeitura (Padrão Nacional)
## Objetivo
Este projeto automatiza o download em lote dos XMLs de Notas Fiscais de Serviço (NFSe) diretamente do portal da prefeitura, evitando a necessidade de baixar manualmente nota por nota.
O sistema:
* abre o Chrome com perfil exclusivo
* o usuário apenas faz login manualmente
* o robô seleciona cada nota automaticamente
* seleciona "NF Nacional"
* clica em "Visualizar XML"
* baixa o arquivo
* fecha o modal corretamente
* passa para a próxima nota
* organiza por empresa/ano/mês
* registra em log para não repetir downloads
## IMPORTANTE (como usar)
1. Execute:
python main.py
2. O Chrome abrirá.
3. Faça login manualmente no portal da prefeitura.
4. Navegue até:
Nota Fiscal → Lista Nota Fiscais
5. Aguarde 40 segundos.
Após isso o robô assumirá automaticamente.
## Estrutura de Pastas
automacao-nfse/
│
├── main.py
├── log.csv
├── downloads/
│ └── EMPRESA/
│ └── ANO/
│ └── MES/
│ └── arquivos.xml
## Tecnologias
* Python 3.11+
* Selenium
* ChromeDriver automático
* XML parsing
## Observações importantes
• O site da prefeitura bloqueia login automatizado
→ por isso o login SEMPRE é manual.
• O sistema utiliza perfil exclusivo do Chrome:
C:\\ChromeRobotProfile
• Não usar o Chrome pessoal.
## Problemas conhecidos
O site ocasionalmente retorna:
HTTP 502
O robô possui tratamento de falha e tenta novamente automaticamente.
Para rodar a lista inteira, sem faixa, use o orquestrador:
python orquestrador_empresas.pyPara processar apenas um lote da planilha:
$env:EMPRESA_INICIO = "1"
$env:EMPRESA_FIM = "100"
python orquestrador_empresas.pySe EMPRESA_INICIO e EMPRESA_FIM ficarem vazios, o comportamento continua igual ao atual: todas as empresas validas da planilha sao processadas.
Ao final de cada execucao, o orquestrador gera um resumo consolidado por empresa na mesma pasta de saida do lote.
Sem faixa:
resumo_execucao_empresas.xlsx- se
openpyxlnao estiver disponivel no ambiente, o fallback e.csv
Com faixa:
resumo_execucao_empresas__lote_001_100.xlsx- se
openpyxlnao estiver disponivel no ambiente, o fallback e.csv
Exemplo em PowerShell:
$env:EMPRESA_INICIO = "1"
$env:EMPRESA_FIM = "100"
python orquestrador_empresas.pyO orquestrador aceita filtros para reexecutar somente subconjuntos uteis.
EMPRESASusa ocodigoda planilha como identificador principal, separado por virgula.FILTRAR_ERRO_TIPOaceita:LOGIN_INVALIDO,ARQUIVO,CAPTCHA,TIMEOUT,ERRO_PORTAL,SEM_MOVIMENTOeDESCONHECIDO.- A ordem aplicada e: faixa ->
EMPRESAS->FILTRAR_ERRO_TIPO. - O filtro por erro usa o
resumo_execucao_empresasdo mesmo escopo e, se ele nao existir, faz fallback parareport_execucao_empresas.
Exemplos em PowerShell:
$env:EMPRESAS = "101,115,833"
python orquestrador_empresas.pyA interface grafica expõe os mesmos filtros da orquestracao:
- faixa de execucao (
EMPRESA_INICIO/EMPRESA_FIM) - empresas explicitas (
EMPRESAS) - filtro por erro (
FILTRAR_ERRO_TIPO)
Quando a faixa for usada, a GUI passa a usar os caminhos do lote para report, checkpoint e resumo_execucao_empresas.
Os arquivos continuam sendo salvos por empresa e, depois disso, sao espelhados em uma pasta geral para consolidacao operacional.
SAIDAS_GERAIS/ISS/<competencia>/SAIDAS_GERAIS/XML_TOMADOS/<competencia>/
Exemplos de nome final:
SAIDAS_GERAIS/ISS/02.2026/00833_ABS_REPRESENTACOES_ISS_02-2026.pdfSAIDAS_GERAIS/XML_TOMADOS/02.2026/00833_ABS_REPRESENTACOES_SERVICOS_TOMADOS_02-2026.xml
O nome espelhado usa, quando disponivel:
- codigo da empresa
- slug ou nome curto da empresa
- tipo do documento
- competencia
- extensao original
O salvamento por empresa continua sendo a fonte primaria de verdade; o espelhamento e secundario e nao substitui o arquivo original.
$env:FILTRAR_ERRO_TIPO = "LOGIN_INVALIDO"
python orquestrador_empresas.py$env:EMPRESA_INICIO = "1"
$env:EMPRESA_FIM = "100"
$env:EMPRESAS = "101,115,833"
$env:FILTRAR_ERRO_TIPO = "LOGIN_INVALIDO"
python orquestrador_empresas.pyAo chegar na etapa manual do login, o sistema tenta posicionar o foco no campo do captcha e deixa a continuacao manual igual ao fluxo atual.