rad / herramientas.py
Moibe's picture
Facilitador de procesamiento de nuevos documentos
93a5ed3
raw
history blame
8.72 kB
import tempfile
import time
from gradio_client import Client, handle_file
import re
async def imageToTemp(image):
try:
with tempfile.NamedTemporaryFile(delete=False, suffix=f"_{image.filename}") as tmp_file:
contents = await image.read()
tmp_file.write(contents)
temp_file_path = tmp_file.name
print(f"Archivo temporal guardado en: {temp_file_path}")
return temp_file_path
except Exception as e:
print(f"Error al procesar la imagen: {e}")
return {"error": "Error al procesar la imagen"}
def listaTextosExtraidos(dict_recibido):
result = dict_recibido['data']
print("Datos extraídos (acceso directo):")
textos_extraidos = []
for item in result:
texto = item[1][0]
print(texto)
textos_extraidos.append(texto)
return textos_extraidos
def simplificaTextos(textos_extraidos):
textos_extraidos_simplificados = [texto.lower().replace(" ", "") for texto in textos_extraidos]
print("Textos extraídos simplificados:")
print(textos_extraidos_simplificados)
return textos_extraidos_simplificados
#Herramientas para DNI Panamá.
def buscaIndexPalabra(arreglo, palabra):
palabra_limpia = palabra.lower().replace(" ", "")
for i, texto_limpio in enumerate(arreglo):
if palabra_limpia in texto_limpio:
return i
return None # Cambiado de 'error' a None
def buscaIndexMultiplesPalabras(arreglo_textos, conceptos_requeridos):
"""
Busca el índice de la primera línea que contiene todas las palabras requeridas (o sus alternativas)
y devuelve la línea con las alternativas corregidas a su forma preferida.
Args:
arreglo (list): Lista de strings de texto extraído (limpios).
conceptos_requeridos (list): Lista de diccionarios, donde cada diccionario define un concepto:
Ej: {'preferida': 'nacimiento', 'alternativas': ['nacimento', 'nacimuento']}
Returns:
tuple: (índice, línea_corregida) si se encuentra, o (None, None) si no se encuentra.
"""
print(f"\n--- Iniciando búsqueda y corrección ---")
# Paso 1: Normalizar los conceptos y prepararlos para la búsqueda y corrección
conceptos_preparados = []
for concepto in conceptos_requeridos:
preferida = concepto['preferida'].lower().replace(" ", "")
alternativas = [alt.lower().replace(" ", "") for alt in concepto.get('alternativas', [])]
# Combinamos la preferida con las alternativas para la búsqueda
todas_las_formas = [preferida] + alternativas
conceptos_preparados.append({
'preferida': preferida,
'todas_las_formas': todas_las_formas,
'alternativas': alternativas # Solo las alternativas para saber cuáles corregir
})
for i, texto_linea in enumerate(arreglo_textos):
texto_linea_lower = texto_linea.lower()
# Variables para seguir el rastro de la línea actual
es_coincidencia_completa = True
palabras_encontradas_en_linea = {} # Almacena {forma_encontrada: forma_preferida}
# Paso 2: Verificar si TODAS las condiciones se cumplen en esta línea
for concepto in conceptos_preparados:
encontrado_en_esta_linea = False
# Buscamos si alguna forma (preferida o alternativa) está en la línea
for forma in concepto['todas_las_formas']:
if forma in texto_linea_lower:
encontrado_en_esta_linea = True
# Guardamos qué forma se encontró y cuál es la preferida
palabras_encontradas_en_linea[forma] = concepto['preferida']
# Hemos encontrado una forma para este concepto, pasamos al siguiente concepto
break
if not encontrado_en_esta_linea:
es_coincidencia_completa = False
print(f"Fallo en línea {i}: No se encontró el concepto '{concepto['preferida']}' ni sus alternativas.")
break # Si falta un concepto, pasamos a la siguiente línea del arreglo
# Paso 3: Si se encontró una coincidencia completa, corregimos la línea y la retornamos
if es_coincidencia_completa:
print(f"ÉXITO: Coincidencia completa en el índice {i}.")
print(f"Texto linea es: {texto_linea}")
linea_corregida = texto_linea
for forma_encontrada, forma_preferida in palabras_encontradas_en_linea.items():
# Nota: Esta corrección simple asume que la palabra encontrada está exactamente igual que en la lista de alternativas (minusculas y sin espacios)
# Para un OCR más variable, necesitarías una lógica de reemplazo más avanzada (ej. re.sub),
# pero para tu caso de "nacimento" a "nacimiento" esto funciona si la palabra se encuentra exactamente.
# Usamos re.sub para reemplazar la palabra encontrada con la preferida, insensible a mayúsculas/minúsculas
# (re.escape para manejar caracteres especiales si los hubiera)
patron_reemplazo = re.compile(re.escape(forma_encontrada), re.IGNORECASE)
# Reemplazamos la palabra encontrada en la línea original con la forma preferida
linea_corregida = patron_reemplazo.sub(forma_preferida, linea_corregida, count=1)
print(f"Línea corregida: '{linea_corregida}'")
# Ahora corregimos la línea original usando la información de las palabras encontradas
arreglo_textos[i] = linea_corregida
return i, arreglo_textos
print(f"\n--- Búsqueda finalizada ---")
print("Ninguna línea contiene todas las palabras requeridas.")
return None, None
########################################################################
def buscarPatronCedula(lista_textos):
for i, texto in enumerate(lista_textos):
if texto and texto[0].isdigit() and '-' in texto:
return i
return 'error'
async def procesaImagen(image):
try:
temp_image = await imageToTemp(image)
client = Client("BuzzwordMx/ai_ocr")
dict_recibido = client.predict(
img=handle_file(temp_image),
lang="en",
api_name="/predict"
)
#Aquí es donde personalizo el proceso:
textos_extraidos = listaTextosExtraidos(dict_recibido)
return textos_extraidos
except Exception as e:
print(f"Error al procesar el archivo: {e}")
return 'Error'
def obtener_fecha(texto):
# El patrón busca:
# - "FECHADENACIMIENTO" (insensible a mayúsculas/minúsculas)
# - Seguido opcionalmente de CERO o MÁS caracteres que NO SEAN UN DÍGITO (lo que inicia la fecha).
# Esto cubrirá ':', '.', espacios, o cualquier otro carácter de separación.
# - Captura el patrón de fecha: \d{1,2}-[A-Za-z0-9]{3}-\d{4}
patron = r"FECHADENACIMIENTO[^\d]*(\d{1,2}-[A-Za-z0-9]{3}-\d{4})"
match = re.search(patron, texto, re.IGNORECASE)
fecha_encontrada = None
if match:
fecha_encontrada = match.group(1)
if fecha_encontrada:
partes_fecha = fecha_encontrada.split('-')
if len(partes_fecha) == 3:
dia = partes_fecha[0]
mes = partes_fecha[1].lower() # Convierte el mes a minúsculas
año = partes_fecha[2]
return f"{dia}-{mes}-{año}"
else:
# Esto se ejecutaría si el formato de la fecha extraída no es el esperado (ej. 2 partes)
return fecha_encontrada
return None # Si no se encontró el patrón de fecha
def obtener_sexo(texto):
# El patrón ahora busca "Sexo" O "Seno" (insensible a mayúsculas/minúsculas)
# Seguido opcionalmente de un ":"
# Seguido opcionalmente de espacios en blanco
# Captura la siguiente letra
patron = r"(Sexo|Seno):?\s*([A-Za-z])"
# re.search busca la primera ocurrencia del patrón en el texto
# re.IGNORECASE hace que la búsqueda sea insensible a mayúsculas/minúsculas para "Sexo" y "Seno"
match = re.search(patron, texto, re.IGNORECASE)
if match:
# match.group(2) devuelve lo que se capturó en el SEGUNDO grupo de paréntesis,
# que es la letra del sexo/seno. match.group(1) sería "Sexo" o "Seno".
return match.group(2)
else:
return None