Arquivos especiais - pdf e csv
Un arquivo PDF inclue textos, gráficos, imagens, tabelas, fontes de caracteres e tudo mais necessário para garantir a representação do documento.
Originalmente um formato proprietário da empresa Adobe, desde 2008 virou um standard ISO e Adobe cedeu seu uso sem royalties para desenvolvedores de software em geral.
O formato PDF é bastante complexo e sua manipulação não é tarefa trivial. Uma descrição do formato na Wikipedia pode ser vista aqui.
Talvez porisso não existe nenhum pacote de software aberto realmente bom para manipular arquivos PDF, afora o próprio software da Adobe, é claro, mas este não é livre nem gratuito. Um pacote aberto recomendado é o Poppler) mas este é escrito na linguagem C++, mais usada por desenvolvedores profissionais.
De modo geral para lêr arquivos PDF e extrair deles o seu texto o melhor é usar o Adobe Reader para abrir o documento PDF e usar a menu File\Save as other...\text para obter o texto perfeitamente extraido.
Entretanto este procedimento é manual e em certas ocasiões pode ser inviável. Por exemplo, podemos estar procurando determinadas palavras no texto em dezenas de milhares de arquivos. Abri-los manualmente um por um é inviável. Em tais casos podemos usar módulos para manipulação de arquivos PDF feitos para o Python. Existem diversos módulos em Python para extrair texto, cada qual com seus trade-offs.
Nesta lição vamos seguir nosso livro referência e instalar o módulo PyPDF2 em nosso sistema. Se você ainda não tem este módulo em seu computador, abra a janela de comando ou o Windows PowerShell e digite
>>pip install PyPDF2
O instalador pip vai buscar o software (usualmente no GitHub) baixar o pacote e proceder sua instalação em Anaconda 3\Lib\site-packages\PyPDF2.Extraindo texto de um arquivo PDF
Neste exemplo vamos extrair o texto de um artigo científico sobre Redes Neurais, que pode ser baixado aqui.O arquivo pdf escolhido 'NN.pdf' é um arquivo pdf "fácil" para extração de texto, contendo essencialmente texto, fórmulas matemáticas e algumas poucas figuras. Arquivos podem ser mais "dificeis" quando contém muitas tabelas formatadas, imagens, etc.
É bom avisar aqui que extrair texto de arquivos PDF nem sempre dá muito certo (a menos que use um pacote como o Adobe...). Surpresas desagradáveis podem acontecer.
Vamos ao exemplo. Após baixar o arquivo NN.pdf coloque-o no mesmo diretório onde está este notebook Jupyter.
Abrindo o arquivo com o Adobe Reader deve aparecer um artigo assim:
Vamos tentar extrair este texto com um script Python usando o módulo PyPDF2. A documentação deste módulo pode ser encontrada aqui.
In [1]:
# vamos importar o módulo essencial
import PyPDF2
O módulo PyPDF2 possue diversos objetos úteis, alguns descritos em nosso livro referência. Para extrair texto usaremos a classe PyPDF2.PdfFileReader. Esta classe recebe como argumento um objeto File
(nosso já conhecido) obtido abrindo o arquivo pdf para leitura em modo
binário e retorna um objeto que representa o documento encontrado dentro
do arquivo pdf, se tudo foi bem.
In [4]:
# cria um objeto da classe PdfFileReader que representa o documento no arquivo pdf
f = open('NN.pdf', 'rb')
pdf = PyPDF2.PdfFileReader(f)
O aviso ameaçador só indica que na criação do objeto pdf alguma anomalia do documento foi encontrada. Isto não afeta nossa extração do texto.
In [5]:
# vejamos quantas páginas foram encontradas
pdf.getNumPages()
Out[5]:
Foram lidas 15 páginas compondo o documento. Podemos conferir este número abrindo o arquivo NN.pdf no Adobe e contando as páginas. São 15 mesmo.
Para extrair o texto de cada página usaremos o método getPage(i).extractText() onde i é o indice da página desejada.
Vejamos a página índice 0.
Para extrair o texto de cada página usaremos o método getPage(i).extractText() onde i é o indice da página desejada.
Vejamos a página índice 0.
In [8]:
# extrai o texto da página indice 0
spg0 = pdf.getPage(0).extractText()
type(spg0)
Out[8]:
O texto da página 0 retornou como um string, na variável spg0. Vejamos um pedaço dele.
In [10]:
# tamanho do texto na página 0
len(spg0)
Out[10]:
In [12]:
spg0[:1000]
Out[12]:
In [13]:
# vamos colocar o texto numa lista de linhas separadas por \n
pg0 = spg0.split('\n')
print(pg0[:15])
In [14]:
# após extrair texto não esqueça de fechar o arquivo
f.close()
Sucesso! O texto extraido pode ser comparado com o artigo original e
está razoavelmente compatível. Algumas coisas que não sairam bem foram
as fórmulas matemáticas, que estão numa linguagem chamada PostScript dentro do documento e claro, figuras não são texto logo não foram extraidas.
Isto encerra este primeiro contato com extração de texto de arquivos PDF. O procedimento acima pode ser encapsulado num módulo Python cujo código está aqui:
Isto encerra este primeiro contato com extração de texto de arquivos PDF. O procedimento acima pode ser encapsulado num módulo Python cujo código está aqui:
import PyPDF2
"""Lê documento PDF e retorna texto extraido"""
# esta função recebe o caminho do arquivo pdf e retorna seu texto extraido num string
def getPDFContent(path):
content = ""
# abre o arquivo pdf e cria um objeto reader
f = open(path, "rb")
pdf = PyPDF2.PdfFileReader(f) # objeto que representa o documento
# Itera pelas páginas do documento
for i in range(0, pdf.getNumPages()):
# Extrai texto da pagina e apenda no string content
content += pdf.getPage(i).extractText() + "\n"
# fecha o arquivo
f.close()
return content
# programa principal, executado ao ativar o módulo
print('Extrai texto de arquivo PDF.')
print(os.getcwd())
print(os.listdir())
print('----------------------------')
print('Entre nome ou caminho de arquivo PDF:')
arq = input()
if not arq.endswith('.pdf'):
arq = arq + '.pdf'
stx = getPDFContent(arq)
txt = stx.split('\n')
print('Texto extraido (primeiros 100 caracteres):')
print('-------------------------------------------')
print()
print(txt[:101])
print()
print('-------------------------------------------')
CSV
Arquivos CSV são arquivos texto cujo conteúdo representa uma planilha Excel. O conteúdo do arquivo CSV são linhas de valores separados por vírgulas. Por exemplo:123, 4, 56, 7, 89 0.1, 3.5, 1, 420, 0
O conteúdo do arquivo CSV é interpretado da seguinte maneira:
- cada linha do arquivo CSV representa uma linha da planilha Excel
- cada elemento entre virgulas representa o valor de uma célula da planilha, naquela linha e na coluna respectiva.
Por exemplo, as vêzes um valor dentro de uma célula pode conter uma vírgula. Como saber ser esta é uma separação de células ou somente um caracter dentro de um valor?
O módulo csv do Python esconde todas estas nuances traiçoeiras atrás de uma interface simples e robusta, que deve sempre ser usada. Manipule diretamente um arquivo CSV somente se você sabe bem o que está fazendo.
A documentação oficial deste módulo pode ser vista aqui.
Classes do módulo CSV
Essencialmente são quatro classes importantes, das quais obtemos objetos correspondentes para manipulação de CSV:- csv.reader(csvfile)
- csv.writer(csvfile)
- csv.DictReader(csvfile)
- csv.DictWriter(csvfile, fieldnames)
Para esta lição vamos usar um arquivo CSV que pode ser baixado aqui.
Baixe-o agora antes de continuar. Após baixar o arquivo coloque-o no mesmo diretório deste notebook.
Usando os objetos csv.reader e csv.writer
Vejamos exemplo de leitura de arquivo CSV usando um objeto csv.reader. Este objeto é iterável, tal como por exemplo uma lista. A cada iteração usando o objeto obtemos uma nova linha do arquivo CSV que está sendo lido.A sequência de passos é:
- abrir o arquivo CSV com open() no modo texto para leitura
- criar um objeto csv.reader a partir do objeto File obtido no passo 1
- iterar sobre as linhas contidas no objeto csv.reader
In [20]:
# vamos importar o módulo csv
import csv
# Criamos um objeto reader para lêr cada linha do arquivo
arq = 'dep1.csv'
# abrimos o arquivo como texto e iteramos por suas linhas, imprimindo cada uma
linhas = []
with open(arq) as csvfile:
# cria objeto reader
rdr = csv.reader(csvfile)
# agora iteramos sobre as linhas do arquivo
for linha in rdr:
print(', '.join(linha))
linhas.append([x for x in linha if not x == ''])
Como vemos a primeira linha é de nomes de colunas, e as demais contém
os dados. Note que só as primeiras 4 colunas tem informação, as demais
são vazias mas fazem parte do documento.
Vejamos agora um exemplo de criação de um arquivo CSV.
Para escrever num arquivo CSV usamos um objeto writer, que é gerado da classe csv.writer().
Vejamos agora um exemplo de criação de um arquivo CSV.
Para escrever num arquivo CSV usamos um objeto writer, que é gerado da classe csv.writer().
In [21]:
# lista de linhas no arquivo com colunas vazias omitidas
linhas
Out[21]:
In [23]:
arq1 = 'exemplo.csv'
with open(arq1, 'w') as csvfile:
wrt = csv.writer(csvfile) # cria o objeto writer
# itera sobre as linhas da lista escrevendo cada uma
for l in linhas:
wrt.writerow(l)
Deve aparecer um arquivo exemplo.csv no diretório
corrente. Abra-o com o Notepad e verifique que os dados foram escritos
corretamente. Inclusive a linha de cabeçalhos (nomes de colunas).
Usando os objetos csv.DictReader e csv.DictWriter
Estes objetos são úteis quando nossos dados estão organizados em formato tipo dicionário, onde a chave de cada item é o nome de uma coluna e o valor do item é o valor da célula na coluna, para uma dada linha da planilha.Por exemplo a última linha no exemplo anterior seria lida da seguinte forma:
{'Nome Parlamentar':'AFONSO HAMM', 'Partido':'PP', 'UF':'RS', 'Titular/Suplente/Efetivado':'T'}
Ou seja, cada linha é lida como um objeto dicionário dict.
In [24]:
# vamos ler o arquivo exemplo.csv
with open('exemplo.csv') as csvfile:
# cria objeto DictReader
rd = csv.DictReader(csvfile)
#itera sobre as linhas do objeto
for row in rd:
# imprimimos somente o nome e o partido
print(row['Nome Parlamentar'], row['Partido'])
Para escrever usando csv.DictWriter o processo é parecido:
In [26]:
# criar arquivo csv com partido e UF somente
with open('partidos.csv', 'w') as f:
# cria o objeto DictWriter: é obrigatório dar nomes das colunas
nomes = ['Partido', 'UF']
wrt = csv.DictWriter(f, fieldnames=nomes)
# escreve os cabeçalhos
wrt.writeheader()
# itera sobre a lista escrevendo linhas
for linha in linhas[1:]:
wrt.writerow({'Partido':linha[1], 'UF':linha[2]})
Deve ter aparecido um arquivo partidos.csv no diretório corrente. Podemos ver seu conteúdo de forma rápida assim:
In [29]:
with open('partidos.csv') as f:
l = f.read().split('\n')
l = [x for x in l if x != '']
print(l)
Isto encerra esta lição.
No comments:
Post a Comment