Procure um PDF para obter informações detalhadas sobre cada caractere de texto, retângulo e linha. Mais: extração de tabela e depuração visual.
Funciona melhor em PDFs gerados por máquina, em vez de digitalizados. Construído em pdfminer.six
.
Atualmente testado em Python 3.8, 3.9, 3.10, 3.11.
As traduções deste documento estão disponíveis em: Chinês (por @hbh112233abc).
Para relatar um bug ou solicitar um recurso, registre um problema. Para fazer uma pergunta ou solicitar assistência com um PDF específico, utilize o fórum de discussões.
pip install pdfplumber
curl " https://raw.githubusercontent.com/jsvine/pdfplumber/stable/examples/pdfs/background-checks.pdf " > background-checks.pdf
pdfplumber < background-checks.pdf > background-checks.csv
A saída será um CSV contendo informações sobre cada caractere, linha e retângulo do PDF.
Argumento | Descrição |
---|---|
--format [format] | csv ou json . O formato json retorna mais informações; inclui metadados em nível de PDF e de página, além de atributos aninhados em dicionário. |
--pages [list of pages] | Uma lista de páginas delimitadas por espaço e indexadas em 1 ou intervalos de páginas hifenizados. Por exemplo, 1, 11-15 , que retornaria dados das páginas 1, 11, 12, 13, 14 e 15. |
--types [list of object types to extract] | As opções são char , rect , line , curve , image , annot , etc. O padrão é todos disponíveis. |
--laparams | Uma string formatada em JSON (por exemplo, '{"detect_vertical": true}' ) para passar para pdfplumber.open(..., laparams=...) . |
--precision [integer] | O número de casas decimais para arredondar números de ponto flutuante. O padrão é sem arredondamento. |
import pdfplumber
with pdfplumber . open ( "path/to/file.pdf" ) as pdf :
first_page = pdf . pages [ 0 ]
print ( first_page . chars [ 0 ])
Para começar a trabalhar com um PDF, chame pdfplumber.open(x)
, onde x
pode ser:
O método open
retorna uma instância da classe pdfplumber.PDF
.
Para carregar um PDF protegido por senha, passe o argumento da palavra-chave password
, por exemplo, pdfplumber.open("file.pdf", password = "test")
.
Para definir parâmetros de análise de layout para o mecanismo de layout do pdfminer.six
, passe o argumento da palavra-chave laparams
, por exemplo, pdfplumber.open("file.pdf", laparams = { "line_overlap": 0.7 })
.
Para pré-normalizar o texto Unicode, passe unicode_norm=...
, onde ...
é uma das quatro formas de normalização Unicode: "NFC"
, "NFD"
, "NFKC"
ou "NFKD"
.
Valores de metadados inválidos são tratados como aviso por padrão. Se isso não for pretendido, passe strict_metadata=True
para o método open
e pdfplumber.open
gerará uma exceção se não for capaz de analisar os metadados.
pdfplumber.PDF
A classe pdfplumber.PDF
de nível superior representa um único PDF e tem duas propriedades principais:
Propriedade | Descrição |
---|---|
.metadata | Um dicionário de pares chave/valor de metadados, extraído dos trailers Info do PDF. Normalmente inclui "CreationDate", "ModDate", "Producer" etc. |
.pages | Uma lista contendo uma instância pdfplumber.Page por página carregada. |
... e também possui o seguinte método:
Método | Descrição |
---|---|
.close() | Chamar esse método chama Page.close() em cada página e também fecha o fluxo do arquivo (exceto nos casos em que o fluxo é externo, ou seja, já aberto e passado diretamente para pdfplumber ). |
pdfplumber.Page
A classe pdfplumber.Page
está no centro do pdfplumber
. A maioria das coisas que você fará com pdfplumber
girará em torno desta aula. Possui estas propriedades principais:
Propriedade | Descrição |
---|---|
.page_number | O número sequencial da página, começando com 1 para a primeira página, 2 para a segunda e assim por diante. |
.width | A largura da página. |
.height | A altura da página. |
.objects / .chars / .lines / .rects / .curves / .images | Cada uma dessas propriedades é uma lista e cada lista contém um dicionário para cada objeto incorporado na página. Para obter mais detalhes, consulte "Objetos" abaixo. |
... e estes métodos principais:
Método | Descrição |
---|---|
.crop(bounding_box, relative=False, strict=True) | Retorna uma versão da página cortada para a caixa delimitadora, que deve ser expressa como 4 tuplas com os valores (x0, top, x1, bottom) . As páginas cortadas retêm objetos que ficam, pelo menos parcialmente, dentro da caixa delimitadora. Se um objeto estiver apenas parcialmente dentro da caixa, suas dimensões serão divididas para caber na caixa delimitadora. Se relative=True , a caixa delimitadora será calculada como um deslocamento do canto superior esquerdo da caixa delimitadora da página, em vez de um posicionamento absoluto. (Consulte o problema nº 245 para obter um exemplo visual e explicação.) Quando strict=True (o padrão), a caixa delimitadora do corte deve estar inteiramente dentro da caixa delimitadora da página. |
.within_bbox(bounding_box, relative=False, strict=True) | Semelhante a .crop , mas retém apenas objetos que estão inteiramente dentro da caixa delimitadora. |
.outside_bbox(bounding_box, relative=False, strict=True) | Semelhante a .crop e .within_bbox , mas retém apenas objetos que ficam totalmente fora da caixa delimitadora. |
.filter(test_function) | Retorna uma versão da página apenas com os .objects para os quais test_function(obj) retorna True . |
... e também possui o seguinte método:
Método | Descrição |
---|---|
.close() | Por padrão, os objetos Page armazenam em cache seu layout e informações do objeto para evitar a necessidade de reprocessá-los. No entanto, ao analisar PDFs grandes, essas propriedades armazenadas em cache podem exigir muita memória. Você pode usar este método para liberar o cache e liberar memória. |
Métodos adicionais são descritos nas seções abaixo:
Cada instância de pdfplumber.PDF
e pdfplumber.Page
fornece acesso a vários tipos de objetos PDF, todos derivados da análise de PDF pdfminer.six
. Cada uma das propriedades a seguir retorna uma lista Python dos objetos correspondentes:
.chars
, cada um representando um único caractere de texto..lines
, cada um representando uma única linha unidimensional..rects
, cada um representando um único retângulo bidimensional..curves
, cada um representando qualquer série de pontos conectados que pdfminer.six
não reconhece como uma linha ou retângulo..images
, cada um representando uma imagem..annots
, cada um representando uma única anotação de PDF (consulte a Seção 8.4 da especificação oficial do PDF para obter detalhes).hyperlinks
, cada um representando uma única anotação PDF do subtipo Link
e tendo um atributo de ação URI
Cada objeto é representado como um simples dict
Python, com as seguintes propriedades:
char
Propriedade | Descrição |
---|---|
page_number | Número da página em que este caractere foi encontrado. |
text | Por exemplo, "z" ou "Z" ou "". |
fontname | Nome da fonte do personagem. |
size | Tamanho da fonte. |
adv | Igual à largura do texto * tamanho da fonte * fator de escala. |
upright | Se o personagem está em pé. |
height | Altura do personagem. |
width | Largura do personagem. |
x0 | Distância do lado esquerdo do caractere ao lado esquerdo da página. |
x1 | Distância do lado direito do caractere ao lado esquerdo da página. |
y0 | Distância da parte inferior do caractere à parte inferior da página. |
y1 | Distância do topo do caractere ao final da página. |
top | Distância do topo do caractere ao topo da página. |
bottom | Distância da parte inferior do caractere ao topo da página. |
doctop | Distância do topo do caractere ao topo do documento. |
matrix | A "matriz de transformação atual" para este personagem. (Veja abaixo para detalhes.) |
mcid | O ID da seção de conteúdo marcada para este caractere, se houver (caso contrário, None ). Atributo experimental. |
tag | A tag da seção de conteúdo marcada para este caractere, se houver (caso contrário, None ). Atributo experimental. |
ncs | TKTK |
stroking_pattern | TKTK |
non_stroking_pattern | TKTK |
stroking_color | A cor do contorno do personagem (ou seja, traço). Consulte docs/colors.md para obter detalhes. |
non_stroking_color | A cor interior do personagem. Consulte docs/colors.md para obter detalhes. |
object_type | "char" |
Nota : A propriedade matrix
de um caractere representa a “matriz de transformação atual”, conforme descrito na Seção 4.2.2 da Referência PDF (6ª Ed.). A matriz controla a escala, inclinação e tradução posicional do personagem. A rotação é uma combinação de escala e inclinação, mas na maioria dos casos pode ser considerada igual à inclinação do eixo x. O submódulo pdfplumber.ctm
define uma classe, CTM
, que auxilia nesses cálculos. Por exemplo:
from pdfplumber . ctm import CTM
my_char = pdf . pages [ 0 ]. chars [ 3 ]
my_char_ctm = CTM ( * my_char [ "matrix" ])
my_char_rotation = my_char_ctm . skew_x
line
Propriedade | Descrição |
---|---|
page_number | Número da página em que esta linha foi encontrada. |
height | Altura da linha. |
width | Largura da linha. |
x0 | Distância da extremidade esquerda ao lado esquerdo da página. |
x1 | Distância da extremidade direita ao lado esquerdo da página. |
y0 | Distância da extremidade inferior ao final da página. |
y1 | Distância da extremidade superior inferior da página. |
top | Distância do topo da linha ao topo da página. |
bottom | Distância da parte inferior da linha ao topo da página. |
doctop | Distância do topo da linha ao topo do documento. |
linewidth | Espessura da linha. |
stroking_color | A cor da linha. Consulte docs/colors.md para obter detalhes. |
non_stroking_color | A cor sem traço especificada para o caminho da linha. Consulte docs/colors.md para obter detalhes. |
mcid | O ID da seção de conteúdo marcada para esta linha, se houver (caso contrário, None ). Atributo experimental. |
tag | A tag da seção de conteúdo marcada para esta linha, se houver (caso contrário, None ). Atributo experimental. |
object_type | "linha" |
rect
Propriedade | Descrição |
---|---|
page_number | Número da página em que este retângulo foi encontrado. |
height | Altura do retângulo. |
width | Largura do retângulo. |
x0 | Distância do lado esquerdo do retângulo ao lado esquerdo da página. |
x1 | Distância do lado direito do retângulo ao lado esquerdo da página. |
y0 | Distância da parte inferior do retângulo à parte inferior da página. |
y1 | Distância do topo do retângulo à parte inferior da página. |
top | Distância do topo do retângulo ao topo da página. |
bottom | Distância da parte inferior do retângulo ao topo da página. |
doctop | Distância do topo do retângulo ao topo do documento. |
linewidth | Espessura da linha. |
stroking_color | A cor do contorno do retângulo. Consulte docs/colors.md para obter detalhes. |
non_stroking_color | A cor de preenchimento do retângulo. Consulte docs/colors.md para obter detalhes. |
mcid | O ID da seção de conteúdo marcada para este retângulo, se houver (caso contrário, None ). Atributo experimental. |
tag | A tag da seção de conteúdo marcada para este retângulo, se houver (caso contrário, None ). Atributo experimental. |
object_type | "reto" |
curve
Propriedade | Descrição |
---|---|
page_number | Número da página em que esta curva foi encontrada. |
pts | Uma lista de tuplas (x, top) indicando os pontos na curva . |
path | Uma lista de tuplas (cmd, *(x, top)) que descrevem a descrição completa do caminho , incluindo (por exemplo) pontos de controle usados nas curvas de Bezier. |
height | Altura da caixa delimitadora da curva. |
width | Largura da caixa delimitadora da curva. |
x0 | Distância do ponto mais à esquerda da curva em relação ao lado esquerdo da página. |
x1 | Distância do ponto mais à direita da curva ao lado esquerdo da página. |
y0 | Distância do ponto mais baixo da curva até a parte inferior da página. |
y1 | Distância do ponto mais alto da curva até a parte inferior da página. |
top | Distância do ponto mais alto da curva ao topo da página. |
bottom | Distância do ponto mais baixo da curva ao topo da página. |
doctop | Distância do ponto mais alto da curva ao topo do documento. |
linewidth | Espessura da linha. |
fill | Se a forma definida pelo caminho da curva está preenchida. |
stroking_color | A cor do contorno da curva. Consulte docs/colors.md para obter detalhes. |
non_stroking_color | A cor de preenchimento da curva. Consulte docs/colors.md para obter detalhes. |
dash | Uma tupla ([dash_array], dash_phase) que descreve o estilo de traço da curva. Consulte a Tabela 4.6 da especificação PDF para obter detalhes. |
mcid | O ID da seção de conteúdo marcada para esta curva, se houver (caso contrário, None ). Atributo experimental. |
tag | A tag da seção de conteúdo marcada para esta curva, se houver (caso contrário, None ). Atributo experimental. |
object_type | "curva" |
Além disso, tanto pdfplumber.PDF
quanto pdfplumber.Page
fornecem acesso a várias listas derivadas de objetos: .rect_edges
(que decompõe cada retângulo em suas quatro linhas), .curve_edges
(que faz o mesmo para objetos curve
) e .edges
(que combina .rect_edges
, .curve_edges
e .lines
).
image
Nota: Embora o posicionamento e as características dos objetos image
estejam disponíveis via pdfplumber
, esta biblioteca não fornece suporte direto para a reconstrução do conteúdo da imagem. Para isso, veja esta sugestão.
Propriedade | Descrição |
---|---|
page_number | Número da página em que a imagem foi encontrada. |
height | Altura da imagem. |
width | Largura da imagem. |
x0 | Distância do lado esquerdo da imagem ao lado esquerdo da página. |
x1 | Distância do lado direito da imagem ao lado esquerdo da página. |
y0 | Distância da parte inferior da imagem à parte inferior da página. |
y1 | Distância do topo da imagem à parte inferior da página. |
top | Distância do topo da imagem ao topo da página. |
bottom | Distância da parte inferior da imagem ao topo da página. |
doctop | Distância do topo do retângulo ao topo do documento. |
srcsize | As dimensões originais da imagem, como uma tupla (width, height) . |
colorspace | Domínio de cores da imagem (por exemplo, RGB). |
bits | O número de bits por componente de cor; por exemplo, 8 corresponde a 255 valores possíveis para cada componente de cor (R, G e B em um espaço de cores RGB). |
stream | Valores de pixel da imagem, como um objeto pdfminer.pdftypes.PDFStream . |
imagemask | Um booleano anulável; if True , "especifica que os dados da imagem devem ser usados como máscara de estêncil para pintura na cor atual." |
mcid | O ID da seção de conteúdo marcada para esta imagem, se houver (caso contrário, None ). Atributo experimental. |
tag | A tag da seção de conteúdo marcada para esta imagem, se houver (caso contrário, None ). Atributo experimental. |
object_type | "imagem" |
pdfminer.six
Se você passar o parâmetro laparams
de manipulação pdfminer.six
para pdfplumber.open(...)
, o dicionário .objects
de cada página também conterá objetos de layout de nível superior de pdfminer.six
, como "textboxhorizontal"
.
As ferramentas de depuração visual do pdfplumber
podem ser úteis para compreender a estrutura de um PDF e os objetos que foram extraídos dele.
PageImage
com .to_image()
Para transformar qualquer página (incluindo páginas cortadas) em um objeto PageImage
, chame my_page.to_image()
. Opcionalmente, você pode passar um dos seguintes argumentos de palavra-chave:
resolution
: O número desejado de pixels por polegada. Padrão: 72
. Tipo: int
.width
: A largura desejada da imagem em pixels. Padrão: não definido, determinado pela resolution
. Tipo: int
.height
: A largura desejada da imagem em pixels. Padrão: não definido, determinado pela resolution
. Tipo: int
.antialias
: se deve usar antialiasing ao criar a imagem. Definir como True
cria imagens com texto e gráficos menos irregulares, mas com tamanhos de arquivo maiores. Padrão: False
. Tipo: bool
.force_mediabox
: use as dimensões .mediabox
da página, em vez das dimensões .cropbox
. Padrão: False
. Tipo: bool
.Por exemplo:
im = my_pdf . pages [ 0 ]. to_image ( resolution = 150 )
A partir de um script ou REPL, im.show()
abrirá a imagem em seu visualizador de imagens local. Mas os objetos PageImage
também funcionam bem com notebooks Jupyter; eles são renderizados automaticamente como saídas de células. Por exemplo:
Nota : .to_image(...)
funciona conforme esperado com instâncias Page.crop(...)
/ CroppedPage
, mas não é capaz de incorporar alterações feitas por meio de instâncias Page.filter(...)
/ FilteredPage
.
PageImage
Método | Descrição |
---|---|
im.reset() | Limpa tudo o que você desenhou até agora. |
im.copy() | Copia a imagem para um novo objeto PageImage . |
im.show() | Abre a imagem no visualizador de imagens local. |
im.save(path_or_fileobject, format="PNG", quantize=True, colors=256, bits=8) | Salva a imagem anotada como um arquivo PNG. Os argumentos padrão quantizam a imagem em uma paleta de 256 cores, salvando o PNG com profundidade de cores de 8 bits. Você pode desabilitar a quantização passando quantize=False ou ajustar o tamanho da paleta de cores passando colors=N . |
Você pode passar coordenadas explícitas ou qualquer objeto PDF pdfplumber
(por exemplo, char, line, rect) para esses métodos.
Método de objeto único | Método em massa | Descrição |
---|---|---|
im.draw_line(line, stroke={color}, stroke_width=1) | im.draw_lines(list_of_lines, **kwargs) | Desenha uma linha a partir de uma line , curve ou 2 tuplas de 2 tuplas (por exemplo, ((x, y), (x, y)) ). |
im.draw_vline(location, stroke={color}, stroke_width=1) | im.draw_vlines(list_of_locations, **kwargs) | Desenha uma linha vertical na coordenada x indicada por location . |
im.draw_hline(location, stroke={color}, stroke_width=1) | im.draw_hlines(list_of_locations, **kwargs) | Desenha uma linha horizontal na coordenada y indicada por location . |
im.draw_rect(bbox_or_obj, fill={color}, stroke={color}, stroke_width=1) | im.draw_rects(list_of_rects, **kwargs) | Desenha um retângulo de um rect , char , etc., ou caixa delimitadora de 4 tuplas. |
im.draw_circle(center_or_obj, radius=5, fill={color}, stroke={color}) | im.draw_circles(list_of_circles, **kwargs) | Desenha um círculo na coordenada (x, y) ou no centro de um char , rect , etc. |
Nota: Os métodos acima são baseados nos métodos ImageDraw
do Pillow, mas os parâmetros foram ajustados para consistência com a nomenclatura fill
/ stroke
/ stroke_width
do SVG.
im.debug_tablefinder(table_settings={})
retornará uma versão do PageImage com as linhas detectadas (em vermelho), interseções (círculos) e tabelas (azul claro) sobrepostas.
pdfplumber
pode extrair texto de qualquer página (incluindo páginas cortadas e derivadas). Também pode tentar preservar o layout desse texto, bem como identificar as coordenadas das palavras e das consultas de pesquisa. Os objetos Page
podem chamar os seguintes métodos de extração de texto:
Método | Descrição |
---|---|
.extract_text(x_tolerance=3, x_tolerance_ratio=None, y_tolerance=3, layout=False, x_density=7.25, y_density=13, line_dir_render=None, char_dir_render=None, **kwargs) | Agrupa todos os objetos de caracteres da página em uma única string.
|
.extract_text_simple(x_tolerance=3, y_tolerance=3) | Uma versão um pouco mais rápida, mas menos flexível, de .extract_text(...) , usando uma lógica mais simples. |
.extract_words(x_tolerance=3, x_tolerance_ratio=None, y_tolerance=3, keep_blank_chars=False, use_text_flow=False, line_dir="ttb", char_dir="ltr", line_dir_rotated="ttb", char_dir_rotated="ltr", extra_attrs=[], split_at_punctuation=False, expand_ligatures=True, return_chars=False) | Retorna uma lista de todas as coisas que parecem palavras e suas caixas delimitadoras. As palavras são consideradas sequências de caracteres onde (para caracteres "verticais") a diferença entre x1 de um caractere e x0 do próximo é menor ou igual a x_tolerance e onde o doctop de um caractere e o doctop do próximo é menor ou igual a y_tolerance . (Se x_tolerance_ratio não for None , o extrator usa um x_tolerance dinâmico igual a x_tolerance_ratio * previous_character["size"] .) Uma abordagem semelhante é adotada para caracteres não verticais, mas em vez disso mede as distâncias verticais, em vez de horizontais, entre eles. Alterar keep_blank_chars para True significará que os caracteres em branco serão tratados como parte de uma palavra, não como um espaço entre as palavras. Alterar use_text_flow para True usará o fluxo de caracteres subjacente do PDF como um guia para ordenar e segmentar as palavras, em vez de pré-classificar os caracteres pela posição x/y. (Isso imita como arrastar um cursor destaca o texto em um PDF; como acontece com isso, a ordem nem sempre parece ser lógica.) Os argumentos line_dir e char_dir informam a este método a direção na qual as linhas/caracteres devem ser lidos; as opções válidas são "ttb" (de cima para baixo), "btt" (de baixo para cima), "ltr" (da esquerda para a direita) e "rtl" (da direita para a esquerda). Os argumentos line_dir_rotated e char_dir_rotated são semelhantes, mas para texto que foi girado. Passar uma lista de extra_attrs (por exemplo, ["fontname", "size"] restringirá cada palavra a caracteres que compartilham exatamente o mesmo valor para cada um desses atributos, e os dictos de palavras resultantes indicarão esses atributos. Definir split_at_punctuation como True irá impor tokens de quebra nas pontuações especificadas por string.punctuation ou você pode especificar a lista de pontuação de separação passando uma string, por exemplo, split_at_punctuation='!"&'()*+,.:;<=>?@[]^`{|}~' . A menos que você defina expand_ligatures=False , ligaduras como fi serão expandidas em suas letras constituintes (por exemplo , fi ). Passar return_chars=True adicionará, a cada dicionário de palavras, uma lista de seus caracteres constituintes, como uma lista no campo "chars" . |
.extract_text_lines(layout=False, strip=True, return_chars=True, **kwargs) | Recurso experimental que retorna uma lista de dicionários representando as linhas de texto da página. O parâmetro strip funciona de forma análoga ao método str.strip() do Python e retorna atributos text sem os espaços em branco ao redor. (Relevante apenas quando layout = True .) Definir return_chars como False excluirá os objetos de caracteres individuais dos dictos de linha de texto retornados. Os **kwargs restantes são aqueles que você passaria para .extract_text(layout=True, ...) . |
.search(pattern, regex=True, case=True, main_group=0, return_groups=True, return_chars=True, layout=False, **kwargs) | Recurso experimental que permite pesquisar o texto de uma página, retornando uma lista de todas as instâncias que correspondem à consulta. Para cada instância, o objeto de dicionário de resposta contém o texto correspondente, qualquer correspondência de grupo regex, as coordenadas da caixa delimitadora e os próprios objetos char. pattern pode ser uma expressão regular compilada, uma expressão regular não compilada ou uma string não regex. Se regex for False , o padrão será tratado como uma string não regex. Se case for False , a pesquisa será realizada sem distinção entre maiúsculas e minúsculas. A configuração main_group restringe os resultados a um grupo regex específico dentro do pattern (o padrão 0 significa a correspondência inteira). Definir return_groups e/ou return_chars como False excluirá a adição das listas de grupos regex e/ou caracteres correspondentes (como "groups" e "chars" aos dictos de retorno). O parâmetro layout funciona como para .extract_text(...) . Os **kwargs restantes são aqueles que você passaria para .extract_text(layout=True, ...) . Nota : As correspondências com largura zero e todos os espaços em branco são descartadas, porque (geralmente) não têm posição explícita na página. |
.dedupe_chars(tolerance=1, extra_attrs=("fontname", "size")) | Retorna uma versão da página com caracteres duplicados — aqueles que compartilham o mesmo texto, posicionamento (dentro da tolerance x/y) e extra_attrs como outros caracteres — removidos. (Veja a edição nº 71 para entender a motivação.) |
A abordagem do pdfplumber
para detecção de tabelas baseia-se fortemente na tese de mestrado de Anssi Nurminen e é inspirada em Tabula. Funciona assim:
Os objetos pdfplumber.Page
podem chamar os seguintes métodos de tabela:
Método | Descrição |
---|---|
.find_tables(table_settings={}) | Retorna uma lista de objetos Table . O objeto Table fornece acesso às propriedades .cells , .rows , .columns e .bbox , bem como ao método .extract(x_tolerance=3, y_tolerance=3) . |
.find_table(table_settings={}) | Semelhante a .find_tables(...) , mas retorna a maior tabela da página, como um objeto Table . Se várias tabelas tiverem o mesmo tamanho — medido pelo número de células — este método retornará a tabela mais próxima do topo da página. |
.extract_tables(table_settings={}) | Retorna o texto extraído de todas as tabelas encontradas na página, representado como uma lista de listas de listas, com a estrutura table -> row -> cell . |
.extract_table(table_settings={}) | Retorna o texto extraído da maior tabela da página (veja .find_table(...) acima), representado como uma lista de listas, com a estrutura row -> cell . |
.debug_tablefinder(table_settings={}) | Retorna uma instância da classe TableFinder , com acesso às propriedades .edges , .intersections , .cells e .tables . |
Por exemplo:
pdf = pdfplumber . open ( "path/to/my.pdf" )
page = pdf . pages [ 0 ]
page . extract_table ()
Clique aqui para um exemplo mais detalhado.
Por padrão, extract_tables
usa as linhas verticais e horizontais da página (ou bordas retangulares) como separadores de células. Mas o método é altamente personalizável através do argumento table_settings
. As configurações possíveis e seus padrões:
{
"vertical_strategy" : "lines" ,
"horizontal_strategy" : "lines" ,
"explicit_vertical_lines" : [],
"explicit_horizontal_lines" : [],
"snap_tolerance" : 3 ,
"snap_x_tolerance" : 3 ,
"snap_y_tolerance" : 3 ,
"join_tolerance" : 3 ,
"join_x_tolerance" : 3 ,
"join_y_tolerance" : 3 ,
"edge_min_length" : 3 ,
"min_words_vertical" : 3 ,
"min_words_horizontal" : 1 ,
"intersection_tolerance" : 3 ,
"intersection_x_tolerance" : 3 ,
"intersection_y_tolerance" : 3 ,
"text_tolerance" : 3 ,
"text_x_tolerance" : 3 ,
"text_y_tolerance" : 3 ,
"text_*" : …, # See below
}
Contexto | Descrição |
---|---|
"vertical_strategy" | Ou "lines" , "lines_strict" , "text" ou "explicit" . Veja a explicação abaixo. |
"horizontal_strategy" | Ou "lines" , "lines_strict" , "text" ou "explicit" . Veja a explicação abaixo. |
"explicit_vertical_lines" | Uma lista de linhas verticais que demarcam explicitamente as células da tabela. Pode ser usado em combinação com qualquer uma das estratégias acima. Os itens da lista devem ser números – indicando a coordenada x de uma linha em toda a altura da página – ou objetos line / rect / curve . |
"explicit_horizontal_lines" | Uma lista de linhas horizontais que demarcam explicitamente as células da tabela. Pode ser usado em combinação com qualquer uma das estratégias acima. Os itens da lista devem ser números – indicando a coordenada y de uma linha em toda a altura da página – ou objetos line / rect / curve . |
"snap_tolerance" , "snap_x_tolerance" , "snap_y_tolerance" | Linhas paralelas dentro dos pontos snap_tolerance serão "encaixadas" na mesma posição horizontal ou vertical. |
"join_tolerance" , "join_x_tolerance" , "join_y_tolerance" | Segmentos de linha na mesma linha infinita, e cujas extremidades estão dentro da join_tolerance entre si, serão "unidos" em um único segmento de linha. |
"edge_min_length" | Arestas menores que edge_min_length serão descartadas antes de tentar reconstruir a tabela. |
"min_words_vertical" | Ao usar "vertical_strategy": "text" , pelo menos min_words_vertical palavras devem compartilhar o mesmo alinhamento. |
"min_words_horizontal" | Ao usar "horizontal_strategy": "text" , pelo menos min_words_horizontal palavras devem compartilhar o mesmo alinhamento. |
"intersection_tolerance" , "intersection_x_tolerance" , "intersection_y_tolerance" | Ao combinar arestas em células, as arestas ortogonais devem estar dentro dos pontos intersection_tolerance para serem consideradas interseccionais. |
"text_*" | Todas as configurações prefixadas com text_ são usadas ao extrair texto de cada tabela descoberta. Todos os argumentos possíveis para Page.extract_text(...) também são válidos aqui. |
"text_x_tolerance" , "text_y_tolerance" | Essas configurações com prefixo text_ também se aplicam ao algoritmo de identificação de tabela quando a estratégia text é usada. Ou seja, quando esse algoritmo procura palavras, ele espera que as letras individuais em cada palavra não estejam separadas por mais do que text_x_tolerance / text_y_tolerance pontos. |
Tanto vertical_strategy
quanto horizontal_strategy
aceitam as seguintes opções:
Estratégia | Descrição |
---|---|
"lines" | Use as linhas gráficas da página — incluindo os lados dos objetos retangulares — como bordas de possíveis células da tabela. |
"lines_strict" | Use as linhas gráficas da página — mas não os lados dos objetos retangulares — como bordas de possíveis células da tabela. |
"text" | Para vertical_strategy : deduza as linhas (imaginárias) que conectam a esquerda, a direita ou o centro das palavras na página e use essas linhas como bordas de possíveis células da tabela. Para horizontal_strategy , o mesmo, mas usando o topo das palavras. |
"explicit" | Use apenas as linhas definidas explicitamente em explicit_vertical_lines / explicit_horizontal_lines . |
Muitas vezes é útil cortar uma página — Page.crop(bounding_box)
— antes de tentar extrair a tabela.
A extração de tabela para pdfplumber
foi radicalmente redesenhada para v0.5.0
e introduziu alterações significativas.
Às vezes, os arquivos PDF podem conter formulários que incluem entradas que as pessoas podem preencher e salvar. Embora os valores nos campos do formulário apareçam como qualquer outro texto em um arquivo PDF, os dados do formulário são tratados de maneira diferente. Se você quiser detalhes sangrentos, consulte a página 671 desta especificação.
pdfplumber
não possui uma interface para trabalhar com dados de formulário, mas você pode acessá-lo usando os wrappers do pdfplumber
em torno pdfminer
.
Por exemplo, este trecho recuperará nomes e valores de campos de formulário e os armazenará em um dicionário.
import pdfplumber
from pdfplumber . utils . pdfinternals import resolve_and_decode , resolve
pdf = pdfplumber . open ( "document_with_form.pdf" )
def parse_field_helper ( form_data , field , prefix = None ):
""" appends any PDF AcroForm field/value pairs in `field` to provided `form_data` list
if `field` has child fields, those will be parsed recursively.
"""
resolved_field = field . resolve ()
field_name = '.' . join ( filter ( lambda x : x , [ prefix , resolve_and_decode ( resolved_field . get ( "T" ))]))
if "Kids" in resolved_field :
for kid_field in resolved_field [ "Kids" ]:
parse_field_helper ( form_data , kid_field , prefix = field_name )
if "T" in resolved_field or "TU" in resolved_field :
# "T" is a field-name, but it's sometimes absent.
# "TU" is the "alternate field name" and is often more human-readable
# your PDF may have one, the other, or both.
alternate_field_name = resolve_and_decode ( resolved_field . get ( "TU" )) if resolved_field . get ( "TU" ) else None
field_value = resolve_and_decode ( resolved_field [ "V" ]) if 'V' in resolved_field else None
form_data . append ([ field_name , alternate_field_name , field_value ])
form_data = []
fields = resolve ( resolve ( pdf . doc . catalog [ "AcroForm" ])[ "Fields" ])
for field in fields :
parse_field_helper ( form_data , field )
Depois de executar este script, form_data
é uma lista contendo uma tupla de três elementos para cada elemento do formulário. Por exemplo, um formulário PDF com um campo de cidade e estado pode ter esta aparência.
[
['STATE.0', 'enter STATE', 'CA'],
['section 2 accident infoRmation.1.0',
'enter city of accident',
'SAN FRANCISCO']
]
Obrigado a @jeremybmerrill por ajudar a manter o código de análise de formulário acima.
extract_table
em um relatório de notificação de ajuste e reciclagem de trabalhadores da Califórnia (WARN). Demonstra depuração visual básica e extração de tabela.extract_table
nos PDFs do Sistema Nacional de Verificação Instantânea de Antecedentes Criminais do FBI. Demonstra como usar a depuração visual para encontrar as configurações ideais de extração de tabela. Também demonstra Page.crop(...)
e Page.extract_text(...).
curve
.Page.extract_text(...)
. Várias outras bibliotecas Python ajudam os usuários a extrair informações de PDFs. Numa visão geral ampla, pdfplumber
se diferencia de outras bibliotecas de processamento de PDF ao combinar estes recursos:
Também é útil saber quais recursos pdfplumber
não oferece:
pdfminer.six
fornece a base para pdfplumber
. Ele se concentra principalmente na análise de PDFs, na análise de layouts de PDF e no posicionamento de objetos e na extração de texto. Ele não fornece ferramentas para extração de tabelas ou depuração visual.
PyPDF2
é uma biblioteca Python pura "capaz de dividir, mesclar, cortar e transformar páginas de arquivos PDF. Ela também pode adicionar dados personalizados, opções de visualização e senhas a arquivos PDF". Ele pode extrair o texto da página, mas não fornece acesso fácil a objetos de forma (retângulos, linhas, etc.), extração de tabelas ou ferramentas de depuração visual.
pymupdf
é substancialmente mais rápido que pdfminer.six
(e, portanto, também pdfplumber
) e pode gerar e modificar PDFs, mas a biblioteca requer a instalação de software não-Python (MuPDF). Ele também não permite acesso fácil a objetos de forma (retângulos, linhas, etc.) e não fornece ferramentas de extração de tabelas ou depuração visual.
camelot
, tabula-py
e pdftables
se concentram principalmente na extração de tabelas. Em alguns casos, eles podem ser mais adequados às tabelas específicas que você está tentando extrair.
Muito obrigado aos seguintes usuários que contribuíram com ideias, recursos e correções:
Solicitações pull são bem-vindas, mas envie primeiro uma proposta, pois a biblioteca está em desenvolvimento ativo.
Mantenedores atuais: