Módulo Python para converter PDF em texto [fechado]


385

Existe algum módulo python para converter arquivos PDF em texto? Eu tentei um pedaço de código encontrado no Activestate que usa pypdf, mas o texto gerado não tinha espaço entre e era inútil.


11
Eu estava procurando uma solução semelhante. Eu só preciso ler o texto do arquivo pdf. Eu não preciso das imagens. O pdfminer é uma boa escolha, mas não encontrei um exemplo simples de como extrair o texto. Finalmente, recebi esta resposta do SO ( stackoverflow.com/questions/5725278/… ) e agora a uso.
Nayan

2
Como a questão foi fechada I anunciado que na Bolsa Pilha dedicada a recomendações de software no caso de alguém quer escrever uma nova resposta: módulo Python para converter PDF para texto
Franck Dernoncourt

11
A única solução que funcionou para mim no conteúdo UTF-8: Apache Tika
Shoham #

Gostaria de atualizar a lista de opções disponíveis para conversão de PDF em texto em Python, GroupDocs.Conversion Cloud SDK for Python converte PDF em texto com precisão.
Tilal Ahmad

Respostas:


142

Experimente o PDFMiner . Ele pode extrair texto de arquivos PDF no formato HTML, SGML ou "PDF marcado".

O formato PDF marcado parece ser o mais limpo, e remover as tags XML deixa apenas o texto simples.

Uma versão do Python 3 está disponível em:


2
Acabei de adicionar uma resposta descrevendo como usar o pdfminer como uma biblioteca.
Codeape

24
Não há suporte para python 3 :(
Karl Adler

11
A resposta que forneci neste tópico pode ser útil para as pessoas que olham para essa resposta e se perguntam como usar a biblioteca. Dou um exemplo de como usar a biblioteca PDFMiner para extrair texto do PDF. Como a documentação é um pouco esparsa, achei que poderia ajudar algumas pessoas.
DuckPuncher

17
sobre python 3, há uma bifurcação com base em seis pypi.python.org/pypi/pdfminer.six
Denis Cornehl

11
exemplo de código em stackoverflow.com/a/26495057/125617
Renaud

136

O pacote PDFMiner mudou desde a publicação do código .

EDIT (novamente):

O PDFMiner foi atualizado novamente na versão 20100213

Você pode verificar a versão que instalou com o seguinte:

>>> import pdfminer
>>> pdfminer.__version__
'20100213'

Aqui está a versão atualizada (com comentários sobre o que eu alterei / adicionei):

def pdf_to_csv(filename):
    from cStringIO import StringIO  #<-- added so you can copy/paste this to try it
    from pdfminer.converter import LTTextItem, TextConverter
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item.objs:
                if isinstance(child, LTTextItem):
                    (_,_,x,y) = child.bbox                   #<-- changed
                    line = lines[int(-y)]
                    line[x] = child.text.encode(self.codec)  #<-- changed

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, codec="utf-8")  #<-- changed 
        # becuase my test documents are utf-8 (note: utf-8 is the default codec)

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(fp)       #<-- changed
    parser.set_document(doc)     #<-- added
    doc.set_parser(parser)       #<-- added
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

Editar (mais uma vez):

Aqui está uma atualização para a versão mais recente em pypi , 20100619p1. Em suma, eu substituído LTTextItemcom LTChare passou uma instância de LAParams para o construtor CsvConverter.

def pdf_to_csv(filename):
    from cStringIO import StringIO  
    from pdfminer.converter import LTChar, TextConverter    #<-- changed
    from pdfminer.layout import LAParams
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item.objs:
                if isinstance(child, LTChar):               #<-- changed
                    (_,_,x,y) = child.bbox                   
                    line = lines[int(-y)]
                    line[x] = child.text.encode(self.codec)

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams())  #<-- changed
        # becuase my test documents are utf-8 (note: utf-8 is the default codec)

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(fp)       
    parser.set_document(doc)     
    doc.set_parser(parser)       
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        if page is not None:
            interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

EDIT (mais uma vez):

Atualizado para a versão 20110515(graças ao Oeufcoque Penteano!):

def pdf_to_csv(filename):
    from cStringIO import StringIO  
    from pdfminer.converter import LTChar, TextConverter
    from pdfminer.layout import LAParams
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item._objs:                #<-- changed
                if isinstance(child, LTChar):
                    (_,_,x,y) = child.bbox                   
                    line = lines[int(-y)]
                    line[x] = child._text.encode(self.codec) #<-- changed

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams())
        # becuase my test documents are utf-8 (note: utf-8 is the default codec)

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(fp)       
    parser.set_document(doc)     
    doc.set_parser(parser)       
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        if page is not None:
            interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

11
In [6]: import pdfminer In [7]: pdfminer .__ version__ Out [7]: '20100424' In [8]: do pdfminer.converter import LTTextItem ImportError: não é possível importar o nome LTTextItem .... LITERALS_DCT_DECODE LTChar LTImage LTPolygon LTTextBox LITERAL_DEVICE LTContainer LTLine LTRect LTTextGroup LITERAL_DEVICE_RGB LTFigura LTPage LTText LTText LTTextLine
Skylar Saveland

@skyl, o código acima é para a versão anterior '20100213'. Na lista de alterações em seus sites, parece que eles foram alterados LTTextItempara LTChar. unixuser.org/~euske/python/pdfminer/index.html#changes
tgray

2
@Oeufcoque Penteano, obrigado! Adicionei outra seção à resposta da versão 20110515por seu comentário.
tgray

11
A resposta dada por @ user3272884 funciona a partir de 01/05/2014
jmunsch 2/14

11
Eu tinha que resolver este mesmo problema hoje, modificou o código de tgray um pouco para extrair informações sobre o espaço em branco, ela postou aqui
tarikki

67

Como nenhuma dessas soluções suporta a versão mais recente do PDFMiner, escrevi uma solução simples que retornará o texto de um pdf usando o PDFMiner. Isso funcionará para aqueles que estão recebendo erros de importação comprocess_pdf

import sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.layout import LAParams
from cStringIO import StringIO

def pdfparser(data):

    fp = file(data, 'rb')
    rsrcmgr = PDFResourceManager()
    retstr = StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    # Create a PDF interpreter object.
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    # Process each page contained in the document.

    for page in PDFPage.get_pages(fp):
        interpreter.process_page(page)
        data =  retstr.getvalue()

    print data

if __name__ == '__main__':
    pdfparser(sys.argv[1])  

Veja abaixo o código que funciona para Python 3:

import sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.layout import LAParams
import io

def pdfparser(data):

    fp = open(data, 'rb')
    rsrcmgr = PDFResourceManager()
    retstr = io.StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    # Create a PDF interpreter object.
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    # Process each page contained in the document.

    for page in PDFPage.get_pages(fp):
        interpreter.process_page(page)
        data =  retstr.getvalue()

    print(data)

if __name__ == '__main__':
    pdfparser(sys.argv[1])  

2
este é o primeiro trecho que eu descobri que realmente funciona com arquivos PDF estranhos (principalmente os e-books gratuitos que podemos obter do packtpub). Todos os outros trechos de código retornam as matérias-primas estranhamente codificadas, mas a sua realmente retorna texto. Obrigado!
precisa saber é o seguinte

Você provavelmente deseja fazer retstr.seek (0) depois de obter dados, ou acumulará texto de todas as páginas.
Tshirtman

2
Para usar com python3, além dos parênteses óbvias após o printcomando, é preciso substituir o filecomando com opene importação StringIOdo pacoteio
McLawrence

11
Uau. Este bloco funcionou perfeitamente na primeira vez em que o copiei. Incrível! Vamos analisar e corrigir os dados e não precisar se preocupar com a entrada.
SecsAndCyber

11
O pdfminer não funciona para python3. esse código não funciona para o pdfminer3k
thang

47

Pdftotext Um programa de código aberto (parte do Xpdf) que você pode chamar do python (não o que você pediu, mas pode ser útil). Eu usei sem problemas. Eu acho que o Google usá-lo no Google Desktop.


6
Essa parece ser a mais útil das ferramentas listadas aqui, com a -layoutopção de manter o texto na mesma posição do PDF. Agora, se eu pudesse descobrir como canalizar o conteúdo de um PDF para ele.
Matthew Schinckel

Após testar várias soluções, essa parece ser a opção mais simples e robusta. Pode ser facilmente empacotado pelo Python usando um arquivo temporário para determinar onde a saída é gravada.
Cerin

Certamente , use '-' como um nome de arquivo para redirecionar a saída para o stdout. Dessa forma, você pode usar subprocess.check_output simples e essa chamada pareceria uma função interna.
Ctrl-C

Apenas para reforçar quem está usando. . . pdftotextparece funcionar muito bem, mas precisa de um segundo argumento que seja um hífen, se você quiser ver os resultados no stdout.
Gordon Linoff

11
Isso converterá recursivamente todos os arquivos PDF iniciando na pasta atual: find . -iname "*.pdf" -exec pdftotext -enc UTF-8 -eol unix -raw {} \;Por padrão, os arquivos gerados recebem o nome original com a .txtextensão.
ccpizza

43

O pyPDF funciona bem (supondo que você esteja trabalhando com PDFs bem formados). Se tudo o que você deseja é o texto (com espaços), basta fazer:

import pyPdf
pdf = pyPdf.PdfFileReader(open(filename, "rb"))
for page in pdf.pages:
    print page.extractText()

Você também pode obter facilmente acesso aos metadados, dados de imagem e assim por diante.

Um comentário no código extractText observa:

Localize todos os comandos de desenho de texto, na ordem em que são fornecidos no fluxo de conteúdo e extraia o texto. Isso funciona bem para alguns arquivos PDF, mas é ruim para outros, dependendo do gerador usado. Isso será refinado no futuro. Não confie na ordem do texto que sai dessa função, pois ela mudará se essa função for mais sofisticada.

Se isso é ou não um problema, depende do que você está fazendo com o texto (por exemplo, se o pedido não importa, tudo bem, ou se o gerador adiciona texto ao fluxo na ordem em que será exibido, tudo bem) . Eu tenho código de extração pyPdf em uso diário, sem problemas.


7
Não há suporte para Unicode :(
PanosJee

7
O pyPdf agora suporta UTF.
lbolla

2
Esta biblioteca parece lixo. Testar em um PDF aleatório me dá o erro "pyPdf.utils.PdfReadError: marcador EOF não encontrado"
Cerin

4
Da pergunta: o texto gerado não tinha espaço entre e era inútil . Eu usei pyPDF e obtive o mesmo resultado - o texto é extraído sem espaços entre as palavras.
Jordan Reiter

Quando executo a função page.extractText (), recebo o erro 'TypeError: Não é possível converter o objeto' bytes 'em str implicitamente' Como posso lidar com isso?
juankysmith

21

Você também pode facilmente usar o pdfminer como uma biblioteca. Você tem acesso ao modelo de conteúdo do pdf e pode criar sua própria extração de texto. Fiz isso para converter o conteúdo em pdf em texto separado por ponto e vírgula, usando o código abaixo.

A função simplesmente classifica os objetos de conteúdo TextItem de acordo com suas coordenadas yex, e gera itens com a mesma coordenada y de uma linha de texto, separando os objetos na mesma linha com ';' personagens.

Usando essa abordagem, consegui extrair texto de um pdf do qual nenhuma outra ferramenta conseguiu extrair conteúdo adequado para análise adicional. Outras ferramentas que experimentei incluem pdftotext, ps2ascii e a ferramenta online pdftextonline.com.

O pdfminer é uma ferramenta inestimável para a raspagem de pdf.


def pdf_to_csv(filename):
    from pdflib.page import TextItem, TextConverter
    from pdflib.pdfparser import PDFDocument, PDFParser
    from pdflib.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item.objs:
                if isinstance(child, TextItem):
                    (_,_,x,y) = child.bbox
                    line = lines[int(-y)]
                    line[x] = child.text

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, "ascii")

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(doc, fp)
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

ATUALIZAÇÃO :

O código acima está escrito em uma versão antiga da API, veja meu comentário abaixo.


Que tipo de plugins você precisa para funcionar corretamente? Eu baixado e instalado pdfminer mas não é o suficiente ...
kxk

11
O código acima está escrito em uma versão antiga do PDFminer. A API mudou nas versões mais recentes (por exemplo, o pacote é agora pdfminer, não pdflib). Eu sugiro que você dê uma olhada na fonte do pdf2txt.pyPDFminer, o código acima foi inspirado na versão antiga desse arquivo.
Codeape

17

slate é um projeto que facilita o uso do PDFMiner de uma biblioteca:

>>> with open('example.pdf') as f:
...    doc = slate.PDF(f)
...
>>> doc
[..., ..., ...]
>>> doc[1]
'Text from page 2...'   

11
Estou recebendo um erro de importação ao executar "import slate": {Arquivo "C: \ Python33 \ lib \ pacotes-de-sites \ slate-0.3-py3.3.egg \ slate_ init_ .py", linha 48, em <module> ImportError: não é possível importar o nome PDF} Mas a classe PDF está lá! Você sabe como resolver isso?
juankysmith

Não, isso parece muito estranho. Você tem dependências?
Tim McNamara

Normalmente, recebo mensagens sobre dependências perdidas, neste caso, recebo a mensagem clássica "Importar arquivo slate" C: \ Python33 \ lib \ pacotes de sites \ slate-0.3-py3.3.egg \ slate_ init_ .py ", linha 48 , no <module> ImportError: não é possível nome de importação PDF"
juankysmith

Slate 0,3 requer pdfminer 20.110.515, de acordo com esta questão GitHub
jabbett

6
Este pacote não é mais mantido. Evite usá-lo. Você não pode até usá-lo em Python 3.5
Sivasubramaniam Arunachalam

9

Eu precisava converter um PDF específico em texto sem formatação dentro de um módulo python. Usei o PDFMiner 20110515, depois de ler a ferramenta pdf2txt.py , escrevi este trecho simples:

from cStringIO import StringIO
from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams

def to_txt(pdf_path):
    input_ = file(pdf_path, 'rb')
    output = StringIO()

    manager = PDFResourceManager()
    converter = TextConverter(manager, output, laparams=LAParams())
    process_pdf(manager, converter, input_)

    return output.getvalue() 

11
def to_txt (pdf_path):
Enviado por George Feștilă

se eu quisesse converter apenas um certo número de páginas, como faria com esse código?
precisa saber é o seguinte

@ psychok7 Você já tentou usar a ferramenta pdf2txt? Parece apoiar esse recurso na versão atual com o sinalizador -p, a implementação parece fácil de seguir e também deve ser fácil de personalizar: github.com/euske/pdfminer/blob/master/tools/pdf2txt.py Espero que ajude! :)
gonz 03/04

11
thanx @gonz, eu tentei para todos os itens acima, mas sua solução acaba por ser perfeito para mim ,, saída com espaços :)
Lazarus

O pdf2txt.py está instalado aqui para mim:C:\Python27\Scripts\pdfminer\tools\pdf2txt.py
The Red Pea

6

Reutilizando o código pdf2txt.py que acompanha o pdfminer; você pode criar uma função que seguirá o caminho para o pdf; opcionalmente, um tipo de saída (txt | html | xml | tag) e opta como a linha de comando pdf2txt {'-o': '/path/to/outfile.txt' ...}. Por padrão, você pode chamar:

convert_pdf(path)

Um arquivo de texto será criado, um irmão no sistema de arquivos para o pdf original.

def convert_pdf(path, outtype='txt', opts={}):
    import sys
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter, process_pdf
    from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter, TagExtractor
    from pdfminer.layout import LAParams
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfdevice import PDFDevice
    from pdfminer.cmapdb import CMapDB

    outfile = path[:-3] + outtype
    outdir = '/'.join(path.split('/')[:-1])

    debug = 0
    # input option
    password = ''
    pagenos = set()
    maxpages = 0
    # output option
    codec = 'utf-8'
    pageno = 1
    scale = 1
    showpageno = True
    laparams = LAParams()
    for (k, v) in opts:
        if k == '-d': debug += 1
        elif k == '-p': pagenos.update( int(x)-1 for x in v.split(',') )
        elif k == '-m': maxpages = int(v)
        elif k == '-P': password = v
        elif k == '-o': outfile = v
        elif k == '-n': laparams = None
        elif k == '-A': laparams.all_texts = True
        elif k == '-D': laparams.writing_mode = v
        elif k == '-M': laparams.char_margin = float(v)
        elif k == '-L': laparams.line_margin = float(v)
        elif k == '-W': laparams.word_margin = float(v)
        elif k == '-O': outdir = v
        elif k == '-t': outtype = v
        elif k == '-c': codec = v
        elif k == '-s': scale = float(v)
    #
    CMapDB.debug = debug
    PDFResourceManager.debug = debug
    PDFDocument.debug = debug
    PDFParser.debug = debug
    PDFPageInterpreter.debug = debug
    PDFDevice.debug = debug
    #
    rsrcmgr = PDFResourceManager()
    if not outtype:
        outtype = 'txt'
        if outfile:
            if outfile.endswith('.htm') or outfile.endswith('.html'):
                outtype = 'html'
            elif outfile.endswith('.xml'):
                outtype = 'xml'
            elif outfile.endswith('.tag'):
                outtype = 'tag'
    if outfile:
        outfp = file(outfile, 'w')
    else:
        outfp = sys.stdout
    if outtype == 'txt':
        device = TextConverter(rsrcmgr, outfp, codec=codec, laparams=laparams)
    elif outtype == 'xml':
        device = XMLConverter(rsrcmgr, outfp, codec=codec, laparams=laparams, outdir=outdir)
    elif outtype == 'html':
        device = HTMLConverter(rsrcmgr, outfp, codec=codec, scale=scale, laparams=laparams, outdir=outdir)
    elif outtype == 'tag':
        device = TagExtractor(rsrcmgr, outfp, codec=codec)
    else:
        return usage()

    fp = file(path, 'rb')
    process_pdf(rsrcmgr, device, fp, pagenos, maxpages=maxpages, password=password)
    fp.close()
    device.close()

    outfp.close()
    return

1

O PDFminer me deu talvez uma linha [página 1 de 7 ...] em todas as páginas de um arquivo pdf que tentei com ele.

A melhor resposta que tenho até agora é pdftoipe, ou o código c ++ é baseado em Xpdf.

veja minha pergunta sobre como é a saída do pdftoipe.



1

Eu usei pdftohtmlcom o -xmlargumento, li o resultado com subprocess.Popen(), que fornecerá x coord, y coord, largura, altura e fonte, de cada trecho de texto no pdf. Eu acho que é isso que 'evince' provavelmente também usa porque as mesmas mensagens de erro são exibidas.

Se você precisar processar dados colunares, isso ficará um pouco mais complicado, pois você precisará inventar um algoritmo adequado ao seu arquivo pdf. O problema é que os programas que produzem arquivos PDF não apresentam necessariamente o texto em nenhum formato lógico. Você pode tentar algoritmos simples de classificação e, às vezes, funciona, mas pode haver pequenos 'stragglers' e 'strays', pedaços de texto que não são colocados na ordem que você imaginava. Então você tem que ser criativo.

Demorei cerca de 5 horas para descobrir um dos pdf em que eu estava trabalhando. Mas funciona muito bem agora. Boa sorte.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.