-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextracdog.py
More file actions
159 lines (122 loc) · 6.58 KB
/
extracdog.py
File metadata and controls
159 lines (122 loc) · 6.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import os
import pandas as pd
import pytesseract
import cv2
import numpy as np
import re
from pdf2image import convert_from_path
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, Border, Side
from datetime import datetime
# Configuração do caminho para o Tesseract OCR (ajuste conforme sua instalação)
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
# Classe para extrair dados de notas fiscais
class ExtratorNotasFiscais:
def __init__(self, diretorio_pdfs, diretorio_saida=None):
self.diretorio_pdfs = diretorio_pdfs
if diretorio_saida is None:
self.diretorio_saida = os.path.join(os.path.dirname(diretorio_pdfs), 'Resultados')
else:
self.diretorio_saida = diretorio_saida
# Criar diretório de saída se não existir
if not os.path.exists(self.diretorio_saida):
os.makedirs(self.diretorio_saida)
# Estrutura para armazenar os dados extraídos
self.dados_extraidos = {
'Número NF': [],
'Data Emissão': [],
'CNPJ Emitente': [],
'Nome Emitente': [],
'Valor Total': [],
'Descrição Produtos': [],
'Arquivo': []
}
def preprocessar_imagem(self, imagem):
# Converter para escala de cinza
gray = cv2.cvtColor(imagem, cv2.COLOR_RGB2GRAY)
# Aplicar threshold adaptativo para melhorar o contraste
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2)
# Remover ruído
kernel = np.ones((1, 1), np.uint8)
img = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
return img
def extrair_texto(self, imagem):
# Pré-processar a imagem
imagem_processada = self.preprocessar_imagem(imagem)
# Extrair texto usando OCR
texto = pytesseract.image_to_string(imagem_processada, lang='por')
return texto
def extrair_dados_nota(self, texto, nome_arquivo):
# Extrair número da nota fiscal
numero_nf = re.search(r'N[Ff]\s*[:-]?\s*(\d+)', texto)
numero_nf = numero_nf.group(1) if numero_nf else 'N/A'
# Extrair data de emissão
data_emissao = re.search(r'(?:Data\s*(?:de)?\s*[Ee]miss[ãa]o|Emitida\s*em)\s*[:-]?\s*(\d{2}/\d{2}/\d{4}|\d{2}\.\d{2}\.\d{4})', texto)
data_emissao = data_emissao.group(1) if data_emissao else 'N/A'
# Extrair CNPJ do emitente
cnpj = re.search(r'(?:CNPJ|C\.N\.P\.J)\s*[:-]?\s*(\d{2}\.\d{3}\.\d{3}/\d{4}-\d{2}|\d{14})', texto)
cnpj = cnpj.group(1) if cnpj else 'N/A'
# Extrair nome do emitente
nome_emitente = re.search(r'(?:Raz[ãa]o\s*Social|Nome|Emitente)\s*[:-]?\s*([^\n\r]+)', texto)
nome_emitente = nome_emitente.group(1) if nome_emitente else 'N/A'
# Extrair valor total
valor_total = re.search(r'(?:Valor\s*Total|Total\s*NF[-]?[eE]|VALOR\s*TOTAL)\s*[:-]?\s*R?\$?\s*(\d+[.,]\d+)', texto)
valor_total = valor_total.group(1) if valor_total else 'N/A'
# Extrair descrição dos produtos (simplificado)
descricao = re.search(r'(?:Descri[çc][ãa]o|Produto|Mercadoria)\s*[:-]?\s*([^\n\r]+)', texto)
descricao = descricao.group(1) if descricao else 'N/A'
# Adicionar dados à estrutura
self.dados_extraidos['Número NF'].append(numero_nf)
self.dados_extraidos['Data Emissão'].append(data_emissao)
self.dados_extraidos['CNPJ Emitente'].append(cnpj)
self.dados_extraidos['Nome Emitente'].append(nome_emitente)
self.dados_extraidos['Valor Total'].append(valor_total)
self.dados_extraidos['Descrição Produtos'].append(descricao)
self.dados_extraidos['Arquivo'].append(nome_arquivo)
def processar_pdfs(self):
# Listar todos os arquivos PDF no diretório
arquivos_pdf = [f for f in os.listdir(self.diretorio_pdfs) if f.lower().endswith('.pdf')]
total_arquivos = len(arquivos_pdf)
print(f"Encontrados {total_arquivos} arquivos PDF para processamento.")
for i, arquivo in enumerate(arquivos_pdf, 1):
caminho_completo = os.path.join(self.diretorio_pdfs, arquivo)
print(f"Processando {i}/{total_arquivos}: {arquivo}")
try:
# Converter PDF para imagens
paginas = convert_from_path(caminho_completo, 300) # DPI 300 para melhor qualidade
# Processar primeira página (geralmente contém os dados principais da NF)
if paginas:
# Converter PIL Image para formato OpenCV
img_cv = cv2.cvtColor(np.array(paginas[0]), cv2.COLOR_RGB2BGR)
# Extrair texto
texto = self.extrair_texto(img_cv)
# Extrair dados da nota fiscal
self.extrair_dados_nota(texto, arquivo)
except Exception as e:
print(f"Erro ao processar {arquivo}: {str(e)}")
def exportar_para_excel(self):
# Criar DataFrame com os dados extraídos
df = pd.DataFrame(self.dados_extraidos)
# Nome do arquivo de saída
data_atual = datetime.now().strftime("%Y%m%d_%H%M%S")
nome_arquivo = f"Notas_Fiscais_Extraidas_{data_atual}.xlsx"
caminho_saida = os.path.join(self.diretorio_saida, nome_arquivo)
# Exportar para Excel
df.to_excel(caminho_saida, index=False, sheet_name='Notas Fiscais')
print(f"\nDados exportados com sucesso para: {caminho_saida}")
return caminho_saida
# Função principal
def main():
# Diretório contendo os PDFs das notas fiscais
diretorio_pdfs = r"Z:\B10_MAT-CONST-CONSULT\A02_REFERENCIAS\02_GOINFRA\07_NOTAS FISCAIS-VISITA-GOINFRA\PDF 123 pag"
# Criar instância do extrator
extrator = ExtratorNotasFiscais(diretorio_pdfs)
# Processar PDFs
extrator.processar_pdfs()
# Exportar dados para Excel
caminho_excel = extrator.exportar_para_excel()
print(f"\nProcessamento concluído! Arquivo Excel gerado: {caminho_excel}")
if __name__ == "__main__":
main()