Já precisou extrair dados de arquivos pdf? Bom, eu já. Eu trabalho com jurimetria e preciso extrair dados de diários oficiais, petições, sentenças, então já viu né…
A primeira pergunta que você precisa fazer antes de ler um pdf é: o arquivo é digital ou digitalizado?
- Se for digital, significa que ele pode ser transcrito diretamente para vários formatos: texto, html, xml e até mesmo
data.frame
s diretamente.
Vamos usar esse exemplo de PDF digital
Se estiver no desktop, é possível ver o documento abaixo:
- Se for digitalizado, você precisará passar um algoritmo de OCR (Optical Character Recognition) para extrair os dados. Provavelmente seu output nesse caso será sempre texto.
Vamos usar esse exemplo de PDF digitalizado
Se estiver no desktop, é possível ver o documento abaixo:
Obs: é possível que seu arquivo seja digitalizado, mas já com uma OCR passada no próprio arquivo. Nesse caso, você pode tratar o documento como digital.
Os créditos dos pacotes abaixo vão todos para o Jeroen Ooms, um dos maiores autores de pacotes da comunidade R
nos últimos dez anos. Sou fã desse cara!
Pacote pdftools
para PDFs digitais
Para instalar o pdftools
no Windows e no Mac, basta rodar
install.packages("pdftools")
Para instalar no Linux, siga as instruções desse link.
PDF para texto
library(tidyverse)
library(stringr)
library(pdftools)
pdf <- '../../static/data/ocr/pdf_digital.pdf'
txt <- pdf_text(pdf)
# imprimindo só os 500 primeiros caracteres da primeira página
cat(str_trunc(txt[1], 500))
## TJ/SP - Comarca de São Paulo
## Movimento Judiciário
##
## Referência: Janeiro de 2011
## Foro: ADAMANTINA
## Unidade: 02 CUMULATIVA
## Planilha: CIVEL
##
##
## Dados da Unidade
## 1. Total de feitos em andamento 2756
## 2. Precatórias 6
## 3. Processos
## 3.1 Processos cíveis 2078
## 3.1.1 De Conhecimento 1111
## 3.1.2 De...
PDF para HTML ou XML
Muitas vezes queremos pegar estruturas no texto que dependem da posição dos elementos. Por exemplo, o texto em um PDF pode estar dividido em várias colunas. Para isso, o ideal seria transformar o arquivo em dados semi-estruturados como HTML ou XML, que separam os elementos do conteúdo do PDF em tags.
Infelizmente, o pdftools
ainda não transforma em HTML nem XML. Para soltar um HTML, vamos montar uma função que chama pdftohtml
do poppler
por command line.
pdf_html <- function(pdf) {
infos <- pdf_info(pdf) # pega infos do pdf
html <- tempfile(fileext = '.html') # cria arquivo temporário
# monta comando a ser executado.
# não sei se funciona em Windows ;)
command <- sprintf('pdftohtml -f 1 -l %s -q -i -s -noframes %s %s',
infos$pages,
normalizePath(pdf),
html)
system(command) # roda comando e salva
txt <- readr::read_file(html) # lê arquivo salvo
file.remove(html) # remove arquivo temporário
txt
}
Você pode brincar com o HTML usando o pacote rvest
:
library(rvest)
html <- pdf_html(pdf)
html %>%
read_html() %>%
html_nodes('div') %>%
head()
## {xml_nodeset (6)}
## [1] <div id="page1-div" style="position:relative;width:1263px;height:892px;"> ...
## [2] <div id="page2-div" style="position:relative;width:1263px;height:892px;"> ...
## [3] <div id="page3-div" style="position:relative;width:1263px;height:892px;"> ...
## [4] <div id="page4-div" style="position:relative;width:1263px;height:892px;"> ...
## [5] <div id="page5-div" style="position:relative;width:1263px;height:892px;"> ...
## [6] <div id="page6-div" style="position:relative;width:1263px;height:892px;"> ...
PDF para tabelas
Use o tabulizer
! Apesar de depender do odiado rJava
(que é um pacote chato de instalar e configurar) o tabulizer
é capaz de extrair os dados diretamente para tabelas, de forma simples e intuitiva.
Para instalar o tabulizer
, siga as instruções dessa página. Já adianto que pode não ser uma tarefa fácil, principalmente por conta do rJava
.
Exemplo: Uma vez montei esse código para estruturar um pdf contendo gastos em obras públicas. Além de usar o tabulizer
, usei os pacotes usuais do tidyverse
e a função abjutils::rm_accent()
para tirar os acentos do texto.
library(tabulizer)
Vamos usar esse pdf de exemplo.
Se estiver no desktop, é possível ver o documento abaixo:
# No meu pc demorou 40 segundos.
tab <- extract_tables('../../static/data/ocr/pdf_compras.pdf')
Essa função serve para arrumar os nomes zoados que vêm no arquivo:
arrumar_nomes <- function(x) {
x %>%
tolower() %>%
str_trim() %>%
str_replace_all('[[:space:]]+', '_') %>%
str_replace_all('%', 'p') %>%
str_replace_all('r\\$', '') %>%
abjutils::rm_accent()
}
Agora veja a magia do tidyverse
posta em prática:
tab_tidy <- tab %>%
# transforma matrizes em tibbles
map(as_tibble) %>%
# empilha
bind_rows() %>%
# arruma nomes a partir da primeira linha
set_names(arrumar_nomes(.[1,])) %>%
# tira primeira linha
slice(-1) %>%
# tira espaços extras
mutate_all(funs(str_replace_all(., '[[:space:]]+', ' '))) %>%
# tira espaços nas bordas
mutate_all(str_trim)
A Tabela 1 mostra as primeiras cinco linhas do resultado.
uf | municipios_atendidos | tipo | subtipo | nome_do_empreendimento | p_de_execucao | total_pac__milhoes | orgao |
---|---|---|---|---|---|---|---|
BA | ILHÉUS/BA | Aeroporto | Terminal de Passageiros | Aeroporto de Ilhéus - PROJETO DE INFRAESTRUTURA E IMPLANTAÇÃO DO MOP | Menor que 50% | 2,1 | Empresa Brasileira de Infraestrutura Aeroportuária |
PR | LONDRINA/PR | Aeroporto | Terminal de Passageiros | Aeroporto de Londrina - IMPLANTAÇÃO DO MÓDULO OPERACIONAL - MOP NO PROCESSAMENTO DE EMBARQUE | Maior que 50% | 4,0 | Empresa Brasileira de Infraestrutura Aeroportuária |
PA | MARABÁ/PA | Aeroporto | Terminal de Passageiros | Aeroporto de Marabá - REFORMA COM AMPLIAÇÃO DO TPS EXISTENTE | Maior que 50% | 7,1 | Empresa Brasileira de Infraestrutura Aeroportuária |
CE | ACOPIARA/CE | Centro de Artes e Esportes Unificados | Modelo 3000m² | Praças - Acopiara - CE - Modelo 3000m² | Menor que 50% | 2,0 | Ministério da Cultura |
SP | AMERICANA/SP | Centro de Artes e Esportes Unificados | Modelo 3000m² | Praças - Americana - SP - Modelo 3000m² | Menor que 50% | 2,4 | Ministério da Cultura |
Pacote tesseract
para PDFs digitalizados
O tesseract
é uma biblioteca escrita em C
e é uma das mais famosas ferramentas abertas para extração de textos a partir de imagens. O pacote em R
de mesmo nome serve para usar essa biblioteca pelo R
sem causar dores de cabeça.
Para instalar o tesseract
no Windows, basta rodar
install.packages('tesseract')
Para Mac e Linux, siga as instruções dessa página.
A principal função do pacote tesseract
é a ocr()
. Seu input é o caminho de uma imagem (pdf, jpeg, tiff, entre outras) e seu output é um texto. Logo, nosso primeiro passo é transformar o pdf em imagem.
pdf <- '../../static/data/ocr/pdf_digitalizado.pdf'
img <- pdf_render_page(
pdf = pdf, # caminho do arquivo
page = 1, # índice da página
dpi = 300 # resolução (pontos por polegada)
)
# salvando imagem num arquivo png
png::writePNG(img, '../../static/data/ocr/pdf_digitalizado_img.png')
Se o PDF tiver mais páginas, você pode fazer um loop para salvar várias imagens. Agora, usamos a função ocr()
no arquivo salvo.
library(tesseract)
txt <- ocr('../../static/data/ocr/pdf_digitalizado_img.png')
# imprimindo só os 300 primeiros caracteres do resultado
cat(str_trunc(txt, 300))
## This is a sample document to test the PDF Image+Text OCR Engine.
## This is a sample document to test the PDF Image+Text OCR Engine.
## This is a sample document to test the PDF Image+Text OCR Engine.
## This is a sample document to test the PDF Image+Text OCR Engine.
## This is a sample document to test the...
Wrap-up
- Se seu pdf for digital, use
pdftools::pdf_text()
. - Se seu pdf for digitalizado, use
pdftools::pdf_render_page()
, depoispng::writePNG()
e por fimtesseract::ocr()
.
É isso. Happy coding ;)