como funciona a extração de texto do pdf
Como funciona a extração de texto de um PDF
Não existem palavras num PDF. Existem glifos numerados em coordenadas. Tudo o que um extrator devolve é uma reconstrução informada, e é por isso que às vezes ela é assustadoramente boa e às vezes é ininteligível.
01
Passo um: encontrar as instruções de desenho
O extrator descomprime o fluxo de conteúdo de cada página e o percorre procurando operadores de texto. O texto vive entre `BT` e `ET` — begin text, end text — e dentro desse bloco um punhado de operadores faz todo o trabalho. `Tf` seleciona uma fonte e um corpo. `Tm` e `Td` definem a posição. `Tj` e `TJ` desenham uma cadeia.
Então a matéria-prima é uma lista assim: em (72, 720), na fonte F1 a 12 pt, desenhe estes bytes. Repita alguns milhares de vezes. É genuinamente só isso que o arquivo contém.
02
Passo dois: transformar códigos de glifo em caracteres — a parte difícil
Os bytes dentro de um `Tj` não são Unicode. São índices na tabela interna de glifos de uma fonte. O byte 0x44 significa "desenhe o glifo 68 desta fonte", e o glifo 68 só é a letra D se a fonte disser que é.
Há dois jeitos de descobrir. As fontes simples carregam uma codificação — muitas vezes uma padrão como WinAnsi, às vezes um vetor Differences próprio que remapeia posições individuais. As fontes compostas, que são quase todas as incorporadas modernas, precisam de um CMap `ToUnicode`: uma tabela explícita no arquivo mapeando cada código de glifo para um caractere Unicode.
Quando esse CMap está presente e correto, a extração é exata. Quando falta, o extrator está adivinhando — em geral recorrendo aos nomes dos glifos na fonte e, na falta disso, aos códigos crus. É essa a origem do texto extraído que sai como uma torrente de consoantes acentuadas ou de caracteres chineses vindos de um documento visivelmente em português. Nada está quebrado; o arquivo simplesmente nunca disse o que os glifos dele significavam.
As fontes em subconjunto pioram isso. Para economizar espaço, um gravador incorpora só os glifos usados e os renumera, então o mapeamento é inteiramente arbitrário e inteiramente dependente do CMap que o gravador pode ou não ter se dado ao trabalho de incluir.
- CMap ToUnicode presente
- Extração exata. O arquivo declara o que cada glifo significa.
- Codificação padrão, sem CMap
- Em geral correto para texto latino simples. Acentos e símbolos começam a escorregar.
- Fonte em subconjunto, sem CMap
- Mojibake. A numeração dos glifos é arbitrária e nada no arquivo a decodifica.
- Texto convertido em contornos
- Não há texto nenhum — as letras são formas vetoriais. Só o OCR consegue ler, exatamente como numa digitalização.
03
Passo três: inventar os espaços
Isso surpreende as pessoas. Um PDF não precisa guardar espaços. Duas palavras são com frequência desenhadas como duas cadeias separadas com um salto de posição entre elas, ou como um único vetor `TJ` com um número negativo no meio — `[(Ol) -20 (á)] TJ` — em que o número é um ajuste de kerning em milésimos de em.
Então o extrator mede. Ele sabe a largura de avanço de cada glifo pela fonte, então sabe onde um caractere *deveria* ter terminado. Se o caractere seguinte começa perceptivelmente mais à direita que isso, ele insere um espaço. Se a folga é pequena, não insere.
O limiar é uma heurística, e é por isso que o texto extraído às vezes chega como `i s t o e s t á e s p a ç a d o` ou, no outro extremo, como `palavrasgrudadas`. O texto justificado é o culpado de sempre: esticar uma linha para preencher a margem alarga os espaços reais até o kerning dentro da palavra começar a parecer um deles.
04
Passo quatro: reconstruir linhas, colunas e ordem de leitura
Agora o extrator tem caracteres com coordenadas e nenhuma noção de linha. Ele agrupa por posição vertical — glifos que compartilham uma linha de base, dentro de uma tolerância, são uma linha — depois ordena cada linha da esquerda para a direita e depois ordena as linhas de cima para baixo.
Isso funciona para uma coluna só. Falha feio com duas, porque a ordem do fluxo de conteúdo é a ordem de desenho, e a ordem por coordenada descendo a página atravessa direto a medianiz. Linha um da coluna um, depois linha um da coluna dois, depois linha dois da coluna um. O resultado são palavras legíveis em ordem ilegível.
Extratores melhores fazem análise de leiaute primeiro: acham as medianizes de espaço em branco, dividem a página em blocos de coluna e extraem cada bloco por inteiro antes de seguir adiante. As tabelas recebem o mesmo tratamento uma dimensão acima — as células são agrupadas em linhas e colunas por alinhamento, porque nada no arquivo diz "tabela". Uma borda traçada são quatro linhas desenhadas na página, e para o extrator não significa nada.
É aqui também que acontece a reconstrução de parágrafos, e onde a hifenização tem de ser desfeita. Uma palavra quebrada numa mudança de linha são duas sequências de glifos e um hífen; juntá-las de volta exige uma regra sobre quando um hífen final é quebra de linha e quando faz parte de uma palavra composta.
05
Os modos de falha, e o que cada um significa
Porque agora você consegue ler o sintoma de trás para a frente até a causa:
- Não sai nada
- Não há camada de texto. A página é uma imagem, ou o texto foi convertido em contornos. Rode OCR.
- Caracteres ilegíveis
- Um CMap ToUnicode ausente ou errado. Os glifos desenharam bem; nada os decodifica.
- Texto na ordem errada
- Leiaute em várias colunas, ou uma ordem de desenho que não bate com a ordem de leitura.
- Espaços faltando ou sobrando
- A heurística da folga. Comum em texto justificado e em títulos com entreletra larga.
- "fi" e "fl" na saída
- Ligaduras. Duas letras desenhadas como um glifo só, e o CMap mapeou isso para o caractere de ligadura único em vez do par.
06
Por que esse é o mesmo problema do PDF para Word
Converter para Word é extração de texto mais uma camada de inferência. Tendo reconstruído caracteres, espaços, linhas e colunas, o conversor precisa adivinhar semântica: esta sequência está em 18 pontos e negrito e fica sozinha acima de um parágrafo, então provavelmente é um título; estas linhas todas começam no mesmo recuo com um glifo de marcador, então isto provavelmente é uma lista.
Cada uma dessas é um palpite tirado de evidência visual, porque o arquivo registra aparência e nada mais. É por isso que a qualidade da conversão varia tanto com a origem. Um PDF exportado do Word, que talvez ainda carregue marcação, converte bem. Um PDF produzido por um motor de composição tipográfica não carrega estrutura nenhuma, e o conversor está lendo exatamente como você leria de uma folha impressa.