feat: implementar extraccion optativa de urls de pdf#2
Open
diegocostares wants to merge 1 commit into
Open
Conversation
Como `pdftotext` descarta los diccionarios de hipervínculos por diseño para enfocarse solo en layout visual, se integra un extractor secundario aislado usando `pdftohtml -xml` (que también viene en poppler-utils) para rescatar los enlaces. Este comportamiento es optativo (vía `extract_urls: true`) para no penalizar el rendimiento de extracción estándar de los usuarios que solo quieren el texto. Signed-off-by: diegocostares <dcosta@buk.cl>
f9dc096 to
6b74cd3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problema
Actualmente, la gema utiliza
pdftotext(parte de la suitepoppler-utils) para extraer texto de archivos PDF. Esta herramienta es excelente para el análisis de layout visual: logra identificar y agrupar correctamente el texto en formatos complejos, como los currículums de múltiples columnas.Sin embargo,
pdftotextomite por diseño la lectura de diccionarios de hipervínculos (anotaciones/Annotsy/URIen el estándar PDF), ya que un link no es texto "visible". Como consecuencia, se pierden las URLs embebidas (ej. un enlace en la palabra "LinkedIn"), afectando procesos posteriores que dependan de recolectar estos datos (como extraer perfiles sociales).Solución omplementada
Dado que extraer URLs implica un costo de procesamiento secundario, la solución se diseñó bajo dos premisas: Responsabilidad Única (SRP) y Ejecución Optativa (para no penalizar a los usuarios que solo quieren el texto base).
Plaintext::PdfUrlExtractor: Se creó una clase aislada responsable de ejecutarpdftohtml -xmlsilenciosamente. Su único trabajo es capturar el XML, buscar coincidencias con Regex para<a href="...">y retornar un listado limpio y único de URLs.Plaintext::PdfHandler#text: Se hizo un override del método. Se sigue ejecutandopdftotextpara obtener el texto con el layout intacto, pero si se pasa el flagextract_urls: trueen el hash de opciones, se invoca al extractor y se apendan las URLs al final del texto con saltos de línea.diagrama de secuencia
sequenceDiagram participant User participant Resolver as Plaintext::Resolver participant Handler as Plaintext::PdfHandler participant CLI1 as OS: pdftotext participant Extractor as Plaintext::PdfUrlExtractor participant CLI2 as OS: pdftohtml User->>Resolver: text(file, {extract_urls: true}) Resolver->>Handler: text(file, options) %% Ejecución Principal (Layout) Handler->>CLI1: exec('/usr/bin/pdftotext file -') CLI1-->>Handler: retorna String (Texto Plano con Layout) %% Ejecución Secundaria Optativa (Links) opt if options[:extract_urls] == true Handler->>Extractor: extract() Extractor->>CLI2: exec('pdftohtml -xml -stdout file') CLI2-->>Extractor: retorna String (XML Crudo) Extractor->>Extractor: Ejecutar Regex (/href="([^"]+)"/) Extractor-->>Handler: retorna Array de Strings (URLs Únicas) Handler->>Handler: Concatenar Texto Principal + \n\n + URLs end Handler-->>Resolver: retorna String FinalAlternativas exploradas y por qué se descartaron
Durante el análisis previo a esta implementación, evaluamos otras alternativas que fueron descartadas por los siguientes motivos:
pdftotextporpdftohtmlcompletamente:pdftohtmles incapaz de respetar columnas. Lee el PDF de forma horizontal destructiva (izquierda a derecha, línea por línea). Si un CV tiene dos columnas ("Experiencia" a la izquierda y "Educación" a la derecha),pdftohtmlmezcla las oraciones de ambas columnas, rompiendo por completo el parseo de IA o Regex aguas abajo.pdftotextes el único que respeta el layout.pdf-reader(Enfoque Ruby Nativo):gemspec. Considerando que el ecosistemapoppler-utilsya viene conpdftohtmlinstalado (es del mismo creador quepdftotext), es mucho más ligero y nativo reutilizar las herramientas C++ existentes en el sistema operativo. Ademas, esto hacia que funcionara mucho mas lento. se trato de hacer ese enfoque en la webapp, pero para hacerlo mas eficiente, se llego a esta propuesta.Cambios clave y validaciones
lib/plaintext/pdf_url_extractor.rb.options[:extract_urls]enPdfHandler.