4 pontos por GN⁺ 2025-05-15 | 1 comentários | Compartilhar no WhatsApp
  • Extrair texto de arquivos PDF é muito mais difícil do que parece, e o PDF é essencialmente um formato de arquivo baseado em gráficos
  • Dentro do PDF, existe basicamente apenas informação de posição dos glifos, com quase nenhum sinal semântico, o que torna a identificação e reconstrução do texto algo complicado
  • Motores de busca exigem entrada limpa em formato HTML, mas as ferramentas open source existentes têm limitações para extrair informações estruturais como títulos e parágrafos
  • Abordagens de visão baseadas em machine learning são as mais precisas, mas há dificuldades para aplicá-las em larga escala por causa de recursos e desempenho
  • Como principal melhoria, foi adotado um algoritmo de identificação de títulos e parágrafos com base em tamanho de fonte e estatísticas, aumentando a precisão da extração

Os desafios de extrair texto de PDFs

  • Motores de busca modernos passaram a ter a capacidade de indexar o formato de arquivo PDF
  • Extrair informações de PDFs não é uma tarefa simples, porque o PDF originalmente é um formato gráfico, não um formato de texto
  • Em vez de texto propriamente dito, há glifos posicionados em coordenadas, o que gera rotação, sobreposição, ordem embaralhada e falta de informação semântica
  • A informação como texto, do jeito que normalmente pensamos, não existe diretamente dentro do arquivo
  • O fato de ser possível pesquisar texto com ctrl+f em um visualizador de PDF é, na verdade, algo surpreendente

As exigências dos motores de busca e os limites da abordagem básica

  • A entrada que os motores de busca mais preferem é HTML limpo
  • Modelos modernos de visão computacional baseados em machine learning apresentam o melhor desempenho, mas
    • processar arquivos PDF grandes (centenas de GB) em um único servidor sem GPU é ineficiente
  • Felizmente, essa área não é totalmente desconhecida, então
    • é possível usar a classe PDFTextStripper do PDFBox como ponto de partida
    • porém, quase não há compreensão da estrutura semântica, como títulos — apenas strings são extraídas

Algoritmo de identificação de títulos

Princípio básico da identificação de títulos

  • Em geral, dá para aproveitar o fato de que títulos costumam aparecer isolados em texto semibold ou mais espesso
    • como títulos sem negrito também são comuns, esse método sozinho tem limitações
  • Em muitos casos, o tamanho da fonte serve como critério para distinguir títulos
    • porém, o tamanho da fonte varia completamente de documento para documento, e não é possível usar um limiar global

Uso de estatísticas de tamanho de fonte

  • Em cada página, geralmente existe um tamanho de fonte dominante (corpo do texto)
  • A página 1 (capa) tem conteúdo descritivo e informações dos autores, então a distribuição de tamanhos de fonte é diferente
  • Como a distribuição de tamanhos de fonte varia por página, usar estatísticas por página, e não do documento inteiro, é mais eficaz
  • Aplicando um aumento de cerca de 20% sobre o tamanho mediano da fonte de cada página, é possível identificar títulos com boa precisão

O problema de unir títulos com várias linhas

  • Por razões de estilo, um título pode ser dividido em várias linhas
    • decidir o momento de unir títulos não é simples, pois podem se misturar títulos de duas ou mais linhas, nomes de autores e outros textos destacados
  • Regras de união:
    • unir linhas consecutivas com o mesmo tamanho de fonte e o mesmo peso funciona bastante bem
    • mas há muitas exceções — unir indiscriminadamente pode levar a resultados errados

Melhorias na identificação de parágrafos

  • O PDFTextStripper identifica parágrafos com base em espaçamento entre linhas e recuo
    • como usa um limiar fixo para separar linhas, há limites para lidar com documentos que usam espaçamentos diferentes
    • especialmente em rascunhos de artigos e preprints, espaçamento de 1,5x a 2x é comum
  • Se o limiar for grande demais, ocorre o erro de incluir títulos dentro do corpo do texto

Separação de parágrafos com base em estatísticas

  • Assim como no tamanho da fonte, também se aplica tratamento estatístico ao espaçamento entre linhas
    • usando a mediana da distância entre linhas, é possível fazer uma separação robusta de parágrafos em qualquer espaçamento

Conclusão

  • Extrair texto de PDFs é algo que, por natureza, não pode ser perfeitamente resolvido
    • porque o próprio formato PDF não foi projetado para essa finalidade
  • Na implementação real, compromissos são inevitáveis, e é importante adotar uma estratégia para obter um resultado “bom o suficiente”
  • Para motores de busca, é mais eficiente focar na extração de sinais significativos, como títulos, resumos e principais pistas estruturais

Texto de amostra de referência

  • Can Education be Standardized? Evidence from Kenya (2022) - Working Paper
    : Guthrie Gray-Lobe, Anthony Keats, Michael Kremer, Isaac Mbiti, Owen W. Ozier
  • The theory of ideas and Plato’s philosophy of mathematics (2019)
    : Dembiński, B.
  • The role of phronesis in Knowledge-Based Economy (2024)
    : Anna Ceglarska, Cymbranowicz Katarzyna

1 comentários

 
GN⁺ 2025-05-15
Opinião do Hacker News
  • Já aconteceu de você achar algo novo e interessante na vida e, de repente, vir uma lembrança vaga de que anos ou meses atrás você já tinha se tornado especialista nisso. Dá até a sensação de ter que recomeçar do zero, como se até os momentos em que você fez coisas muito legais tivessem sumido da cabeça. Tenho uma lembrança difusa de ter feito algo incrível com PDF e OCR uns 6 ou 7 anos atrás. Fui procurar no Google e o nome “tesseract” soou familiar

    • Por volta de 2006, eu ficava irritado com o fato de não conseguir copiar texto de artigos científicos em múltiplas colunas no iRex, um e-reader hackeável daquela época. Na época, o visualizador de PDF usava poppler, então modifiquei o poppler para inferir a ordem de leitura em documentos com múltiplas colunas. Para isso, me baseei no algoritmo de OCR do Thomas Breuel, autor do tesseract. Era uma espécie de hack heurístico e não combinava bem com a API de acessibilidade. A seleção em múltiplas colunas foi introduzida, mas tive dificuldade para convencer os mantenedores. De todo modo, foi assim que o kpdf ganhou seleção multicoluna. Hoje acho muito mais sensato usar o próprio tesseract para esse tipo de tarefa

    • Não dá para recuperar as dezenas de anos de vida humana desperdiçadas por causa do formato PDF. Fico me perguntando quando essa loucura vai acabar

    • O Tesseract foi por um tempo o melhor OCR open source. Mas hoje acho o docTR superior em precisão e aceleração por GPU. O docTR tem uma arquitetura de pipeline em que é possível combinar vários modelos de detecção e reconhecimento de texto. Também dá para treinar e ajustar em PyTorch ou TensorFlow, então é possível extrair desempenho muito melhor para domínios específicos

    • A vida é assim. Sempre que termino um projeto, penso: “agora sou especialista nessa área. Mas provavelmente nunca mais vou mexer nisso”. Porque na vez seguinte vou recomeçar do zero em um assunto completamente novo

    • Outro dia alguém me perguntou sobre C++ e eu disse que “nunca tinha trabalhado seriamente com isso”. Aí depois lembrei que, uns 20 anos atrás, escrevi o código cliente de um mensageiro instantâneo privado em Borland C++, usado por milhares de pessoas. Isso acontece com frequência

    • Não posso saber tudo o que se passa na sua cabeça, mas provavelmente era tesseract mesmo. Já tive uma experiência parecida, no meu caso foi há uns 12 anos

    • Quando o HQ estava em alta, fiz um resolvedor automático de quiz do HQ com tesseract. Tirava screenshot da tela da pergunta do app, enviava para uma pequena API e depois pesquisava o texto da pergunta no Google, contando quantas vezes cada resposta aparecia para ranquear por probabilidade. Não era preciso e era um método simples, mas foi muito divertido de fazer

    • Isso não é muito diferente de uma formiga-de-fogo que vê uma folha voar com o vento e simplesmente procura outra folha

    • Como foi há 7 ou 8 anos, quando eu estava na casa dos 20, ainda lembro vividamente. Talvez exista alguma diferença de idade aí. Ou então recomendo fazer um check-up também

  • Eu gostaria que existisse uma ferramenta, como as devtools do navegador (“inspecionar elemento”), para “ver” o content stream do PDF em nível de código-fonte — o BT…ET em volta do texto, os vários operadores que definem fonte e coordenadas etc. — e compará-lo/analisá-lo lado a lado com o resultado renderizado. É diferente do fluxo atual em que modelos de visão processam PDFs “olhando” para eles, mas eu queria entender profundamente que informação realmente existe dentro do PDF. Algumas ferramentas existem, mas só mostram até o nível de objeto e não entram no content stream em si. Quero um ambiente em que seja possível comparar e analisar lado a lado, como em HTML, o código real do stream de um PDF de exemplo e o resultado renderizado, para ver que parte corresponde a quê e como aquilo é expresso

    • Acho que dá para ter uma experiência quase igual usando o PDF.js da Mozilla para renderizar o PDF em DOM. Por exemplo, operadores como Tj ou TJ viram um <span> ou um conjunto deles. Imagino que seja por precisar ser fiel ao documento original

    • Recomendo experimentar a ferramenta cpdf (fui eu que fiz). Com as opções -output-json e -output-json-parse-content-streams do cpdf, dá para converter PDFs em JSON e fazer vários tipos de experimento. Também é possível voltar de JSON para PDF. Mas não oferece interação em tempo real

    • Parece que você está procurando uma ferramenta gratuita ou open source, mas lembro que o Acrobat Pro antigamente oferecia algo bem parecido. Só que, em vez de inspecionar a página, ele navegava pela árvore de conteúdo e mostrava apenas até o nível de objeto/stream, sem chegar aos comandos individuais

    • “Estamos construindo na Tensorlake uma combinação de ‘ver o PDF como um humano com um modelo de visão’ e ‘saber de fato que dados existem no PDF’ (eu trabalho lá). Não se trata só de ler texto, mas de realmente entender tabelas, imagens, fórmulas, manuscrito etc. para poder extrair dados em Markdown/JSON e aplicar isso em apps de AI, LLM e afins” https://tensorlake.ai

    • Não é exatamente o nível que você quer, mas vale dar uma olhada neste notebook que oferece um inspetor para mostrar ‘ao vivo’ várias operações de desenho internas do PDF https://observablehq.com/@player1537/pdf-utilities

  • Passei anos na Apple focado nesse problema. O ponto central é aceitar que “é tudo geometria” e usar um algoritmo que faça clustering para diferenciar espaçamento entre palavras e espaçamento entre letras. Funciona bem na maioria dos PDFs, mas, olhando de perto, a variedade é tão grande que alguns casos são decepcionantes. Se eu fosse fazer isso hoje de novo, tiraria o OCR completamente e partiria de informações geométricas, mas com machine learning acoplado. Se você gerar PDFs com texto conhecido de antemão, ainda dá para automatizar a construção dos dados de treino para aprendizado de máquina. (Existe um vídeo da apresentação do Bertrand Serlet na WWDC 2009)

  • Eu diria que não existe um único problema de ‘PDF para texto’, mas sim 3 categorias: (1) OCR confiável (para busca, entrada em banco vetorial etc.), (2) extração de dados estruturados (extrair só valores específicos), (3) automação de pipeline documental completo (por exemplo, automação de hipoteca). O objetivo da Marginalia é o (1), e hoje, graças a coisas como Gemini Flash, OCR ficou barato e generalizado. Mas (2) e (3) são bem mais difíceis, e a automação total ainda exige muito esforço humano na construção de datasets, desenho de pipeline, detecção de incerteza e intervenção manual, fine-tuning etc. O futuro está nessa direção. (Administro uma empresa de processamento de documentos com LLM) https://extend.ai

    • Eu acrescentaria uma (4): OCR confiável e extração semântica em documentos de formatos variados, ou seja, soluções para acessibilidade. Isso é difícil porque, ao contrário de fluxos de trabalho comuns, os tipos de documento do usuário são imprevisíveis; é preciso extrair também elementos não textuais como tabelas, cabeçalhos/rodapés/anotações/fórmulas; há forte exigência de minimizar erros, então não se pode usar OCR além do necessário; o texto embutido e o conteúdo renderizado podem não coincidir (texto oculto ou composições não padronizadas etc.); costuma rodar em apps locais, o que dificulta usar servidor; e ainda é preciso suporte a Forms para documentos de uso com impressora braille. Hoje não existe solução que resolva tudo isso completamente

    • Há quem diga que simplificou o pipeline de OCR usando VLM, mas fica o alerta: em documentos realmente complexos isso é muito difícil. Vai muito bem em rótulos simples de imagem e serve para documentos muito simples, mas em documentos com tabelas, cabeçalhos, resumos estruturados etc. aparece alucinação de forma severa. Na prática, quase não dá para usar

    • Tenho enfrentado vários problemas ao converter para Markdown, como detecção de cabeçalhos. OCR hoje em dia é excelente, mas preservar a estrutura do documento inteiro é muito mais difícil. Tenho obtido resultados razoáveis passando por LLM várias vezes para extrair a estrutura e inserindo contexto por página

  • Uma solução melhor seria anexar ao PDF o documento-fonte editável. Isso é fácil de fazer no LibreOffice. Em geral, também não ocupa tanto espaço e permite saber claramente o significado do texto. Continua funcionando normalmente nos leitores de PDF existentes

    • Quando o problema é extrair texto de PDFs já existentes, fico em dúvida sobre o quanto esse tipo de conselho sobre como produzir PDF realmente ajuda. Queria saber quando esse tipo de solução vai começar a fazer efeito de verdade

    • Faz sentido, mas isso cria o risco de o documento-fonte e o PDF renderizado terem conteúdos totalmente diferentes

    • Concordo, mas isso só vale se os interesses de quem cria o PDF e de quem consome o PDF estiverem alinhados. Na área de e-Discovery, é comum que o advogado da outra parte entregue o material convertido de propósito para PDF para dificultar o uso dos dados. Como consequência, defensores públicos com menos recursos acabam gastando mais tempo para processar o material e sofrem desvantagem real. Para evitar isso, acho que a lei deveria exigir entrega compulsória de vários tipos de dados em formatos padrão legíveis por máquina

    • Se você puder ter acesso ao documento-fonte, anexá-lo dentro do PDF é excelente. Só que, na maioria dos casos, você não tem esse nível de controle

    • A maior parte do problema real são PDFs legados. Na nossa empresa temos milhares deles acumulados, e alguns são scans horríveis. Alguns até têm OCR embutido da Adobe, mas a maioria não tem nada

  • O PDF abaixo na verdade é um arquivo .txt. Você pode trocar a extensão para .pdf, abrir em um visualizador de PDF e até editar diretamente num editor de texto para controlar várias coisas como o que aparece na tela, fonte, tamanho da fonte, espaçamento entre linhas, número de caracteres por página, número de linhas, tamanho do papel etc. (inclui exemplo de texto PDF real)

    • O PDF também pode embutir streams binários. PDF não é texto; é um formato feito para layout e gráficos. Como no exemplo, às vezes cada linha pode aparecer de uma vez, mas na prática também pode ser representado por letra, por palavra ou até fora de ordem

    • PDF significa “Portable Document Format”. Ele é codificado como um arquivo ASCII de 7 bits, o que lhe dá grande portabilidade entre diferentes dispositivos e sistemas operacionais. (Referência: link da documentação oficial da Adobe)

    • Esse exemplo é o ‘Hello World’ do PDF. PDFs mais recentes normalmente comprimem objetos (obj) com deflate e agrupam esses objetos dentro de streams, o que torna tudo mais complexo. Por isso, analisar procurando coisas como 6 0 Obj em texto simples fica muito difícil

  • Extrair texto de PDF, especialmente texto estruturado, está longe de ser simples. Tabelas em HTML costumam ser relativamente fáceis de extrair, mas em PDF elas só parecem tabelas por causa das coordenadas de renderização; na prática, texto e gráficos ficam espalhados. Eu mesmo uso uma abordagem de converter PDF para HTML com as utils do Poppler, depois localizar os cabeçalhos da tabela e identificar as colunas pelo eixo x de cada valor para extrair os dados linha a linha. Parece meio tosco, mas é mais confiável do que fazer isso a partir de um .txt alinhado

    • Eu me irritava por não conseguir extrair dados de PDF como faço com páginas web e BeautifulSoup, então acabei criando uma biblioteca com esse tipo de interface. (exemplo no estilo page.find) O inferno é que cada PDF tem casos tão diferentes que estou juntando know-how de extração e exemplos de PDFs bizarros na própria biblioteca https://jsoma.github.io/natural-pdf/ , https://badpdfs.com/

    • Um dia eu gostaria de extrair dados tabulares de PDFs para o meu software de processamento de dados. Se alguém conhecer uma biblioteca gratuita ou muito barata que eu possa integrar a um app em C++, aceito sugestões

    • Existem documentos, como os de órgãos públicos, em que o texto que aparece para impressão e o texto realmente extraído são completamente diferentes. Esse tipo de caso aparece de vez em quando

    • PDF é, em essência, um formato de markup/XML. Um mesmo PDF pode ser produzido de inúmeras maneiras. Se for exportado de uma ferramenta gráfica, sai um PDF com mistura de gráficos e texto; se vier de um processador de texto, tende a ser um PDF mais centrado em texto. A forma como o aplicativo de origem trata a informação afeta muito como o PDF é gerado. Entre utilitários prontos, famílias de produtos como cisdem servem mais ou menos para extrair algum dado estruturado. Mas cada tarefa pede a ferramenta certa

  • Um dos meus exemplos favoritos é o PDF deste artigo (link incluído). A primeira página tem texto típico em duas colunas, um cabeçalho central, texto invadindo o espaço entre colunas e elementos que mudam comprimento de linha e indentação. Os cabeçalhos de página também mudam entre páginas pares e ímpares, e as regras dos cabeçalhos de seção não são consistentes. Os parágrafos também nem sempre têm indentação e há variações no espaçamento entre linhas. É um pacote completo de problemas diferentes

    • A API CoreGraphics do macOS fornece o texto do PDF página por página, na ordem codificada no dicionário. Em 95% dos casos isso funcionava muito bem, e o PDFKit e o Preview também não tiveram grandes problemas por anos. Até texto em duas colunas normalmente entrava no PDF seguindo a ordem do buffer do processador de texto original, então o fluxo do conteúdo saía correto. Já cabeçalhos/rodapés são tratados de forma totalmente diferente por cada app interno, então ficam imprevisíveis
  • Quando tentei fazer um parser de PDF simples por conta própria, fiquei surpreso com a forma como o formato funciona. Por isso sempre achei estranho ele ser tão usado para fins centrados em texto. Por exemplo, no caso de invoices, um sistema digital deveria ser fácil para extração de dados e, para humanos, oferecer uma apresentação formatada. Então eu gostaria que o setor de tecnologia migrasse gradualmente para formatos melhores

    • Antigamente XML+XSLT chegava bem perto de cumprir esse papel, mas infelizmente os navegadores já não dão mais suporte para arquivos XML locais. Só XML vindo de servidor remoto
  • Extrair ‘informação útil’ de PDFs é exatamente o trabalho da Tensorlake (https://tensorlake.ai). PDF contém não só texto, mas também tabelas, imagens, fórmulas, manuscrito, texto riscado e várias outras informações; por isso, como desenvolvedores, não basta apenas “ler” texto, precisamos “entendê-lo”. (Divulgando que sou funcionário)