Parsowanie PDF za pomocą PyMuPDF i pdfplumber
Programowe wyodrębnianie tekstu, tabel i metadanych z plików PDF.
Parsowanie PDF za pomocą PyMuPDF i pdfplumber to bezpłatna lekcja AI Agents na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Agents, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Agents zawiera 4 lekcji w sumie.
Dlaczego parsowanie plików PDF nie jest proste
Pliki PDF są formatem prezentacji, a nie formatem danych. Tekst jest przechowywany jako glify umieszczone w określonych pozycjach, a nie jako logiczne akapity. Wyodrębnianie znaczącego tekstu wymaga zrozumienia układu, kolejności czytania i właściwości czcionek oraz obsługi przypadków brzegowych, takich jak układy wielokolumnowe, nagłówki i stopki czy osadzone obrazy.
Dwie biblioteki zdecydowanie dominują w tym obszarze: PyMuPDF (szybkość) i pdfplumber (wyodrębnianie tabel).
Podstawy PyMuPDF
PyMuPDF (importowany jako fitz) to najszybsza biblioteka PDF dla Pythona. Obsługuje wyodrębnianie tekstu, metadane, obrazy i renderowanie. Należy zainstalować za pomocą pip install pymupdf.
import fitz # PyMuPDF
# Open a PDF
doc = fitz.open('document.pdf')
print(f'Pages: {len(doc)}')
print(f'Metadata: {doc.metadata}')
# Extract text from all pages
full_text = ''
for page_num in range(len(doc)):
page = doc[page_num]
text = page.get_text() # plain text extraction
full_text += f'--- Page {page_num + 1} ---\n{text}\n'
doc.close()
print(full_text[:500])Tryby wyodrębniania tekstu w PyMuPDF
page.get_text() obsługuje różne formaty danych wyjściowych. Należy użyć 'text' dla zwykłego tekstu, 'blocks' dla bloków tekstu z prostokątami ograniczającymi oraz 'dict' dla bogatych danych strukturalnych zawierających między innymi nazwy i rozmiary czcionek.
import fitz
doc = fitz.open('report.pdf')
page = doc[0]
# Mode 1: plain text
plain = page.get_text('text')
# Mode 2: blocks (each block has bbox + text)
blocks = page.get_text('blocks')
for block in blocks:
x0, y0, x1, y1, text, block_no, block_type = block
if block_type == 0: # text block (1 = image)
print(f'Block at ({x0:.0f},{y0:.0f}): {text[:80]}')
# Mode 3: dict (full detail including font info)
page_dict = page.get_text('dict')
for block in page_dict['blocks']:
if block.get('type') == 0: # text
for line in block['lines']:
for span in line['spans']:
print(f"Font: {span['font']}, Size: {span['size']:.1f}, Text: {span['text']}")
doc.close()Wyodrębnianie metadanych stron
Metadane stron pomagają agentom zrozumieć strukturę dokumentu: liczbę stron, tytuł dokumentu, autora, datę utworzenia i wymiary stron. PyMuPDF udostępnia wszystkie te informacje.
import fitz
def extract_pdf_metadata(filepath):
doc = fitz.open(filepath)
meta = doc.metadata
info = {
'title': meta.get('title', 'Unknown'),
'author': meta.get('author', 'Unknown'),
'subject': meta.get('subject', ''),
'creator': meta.get('creator', ''),
'created': meta.get('creationDate', ''),
'modified': meta.get('modDate', ''),
'pages': len(doc),
'page_size': {
'width': doc[0].rect.width,
'height': doc[0].rect.height
}
}
doc.close()
return info
meta = extract_pdf_metadata('contract.pdf')
print(f"Title: {meta['title']}, Pages: {meta['pages']}")pdfplumber do wyodrębniania tabel
pdfplumber doskonale sprawdza się w wyodrębnianiu tabel z plików PDF. Wykorzystuje analizę geometryczną do wykrywania granic komórek, nawet w plikach PDF bez jawnego oznaczenia tabel.
Należy zainstalować za pomocą pip install pdfplumber.
import pdfplumber
with pdfplumber.open('financial_report.pdf') as pdf:
for page_num, page in enumerate(pdf.pages):
tables = page.extract_tables()
for table_idx, table in enumerate(tables):
print(f'Page {page_num+1}, Table {table_idx+1}:')
# table is a list of rows; each row is a list of cell strings
headers = table[0]
for row in table[1:]:
row_dict = dict(zip(headers, row))
print(row_dict)Ustawienia tabel w pdfplumber
Wyodrębnianie tabel za pomocą pdfplumber można dostosować ustawieniami obsługującymi różne style tabel: jawne linie, kolumny rozdzielone spacjami lub układy mieszane.
import pdfplumber
# Custom table settings for borderless tables
table_settings = {
'vertical_strategy': 'text', # 'lines', 'lines_strict', 'text', 'explicit'
'horizontal_strategy': 'text',
'snap_tolerance': 5,
'join_tolerance': 3,
'edge_min_length': 50,
'min_words_vertical': 3,
'min_words_horizontal': 1
}
with pdfplumber.open('nolines_table.pdf') as pdf:
page = pdf.pages[0]
table = page.extract_table(table_settings)
if table:
import csv
import io
output = io.StringIO()
writer = csv.writer(output)
writer.writerows(table)
csv_string = output.getvalue()
print(csv_string[:300])Obsługa układów wielokolumnowych
Artykuły naukowe i gazety wykorzystują układy wielokolumnowe. Naiwne wyodrębnianie tekstu odczytuje zawartość od lewej do prawej, przechodząc między kolumnami, i tworzy niespójny tekst. Należy temu zapobiec, sortując bloki tekstu najpierw według kolumn.
import fitz
def extract_multicolumn_text(page, n_columns=2):
page_width = page.rect.width
col_width = page_width / n_columns
blocks = page.get_text('blocks')
# Filter text blocks only
text_blocks = [b for b in blocks if b[6] == 0]
# Assign each block to a column based on x position
columns = [[] for _ in range(n_columns)]
for block in text_blocks:
x0 = block[0]
col_idx = min(int(x0 / col_width), n_columns - 1)
columns[col_idx].append(block)
# Sort each column by vertical position
for col in columns:
col.sort(key=lambda b: b[1]) # sort by y0
# Read columns left to right
full_text = ''
for col in columns:
for block in col:
full_text += block[4] + '\n'
return full_textFiltrowanie nagłówków i stopek
Nagłówki i stopki plików PDF powtarzają się na każdej stronie i zanieczyszczają wyodrębniony tekst. Należy identyfikować je na podstawie położenia w pionie (w górnych lub dolnych 10% strony) i wykluczać z wyodrębniania treści.
import fitz
def extract_without_headers_footers(page, margin_ratio=0.08):
page_height = page.rect.height
top_margin = page_height * margin_ratio
bottom_margin = page_height * (1 - margin_ratio)
blocks = page.get_text('blocks')
content_blocks = []
for block in blocks:
x0, y0, x1, y1, text, block_no, block_type = block
if block_type != 0:
continue # skip image blocks
# Skip blocks in header or footer zone
if y0 < top_margin or y1 > bottom_margin:
continue
content_blocks.append(text)
return '\n'.join(content_blocks)Dzielenie tekstu PDF na fragmenty dla agentów
Długie pliki PDF trzeba dzielić na fragmenty na potrzeby osadzania i pobierania. Fragmenty należy wyznaczać w naturalnych miejscach: na granicach akapitów, sekcji lub stron. Należy uwzględnić nakładanie się fragmentów, aby nie przecinać kontekstu w środku zdania.
import fitz
def pdf_to_chunks(filepath, chunk_size=1000, overlap=200):
doc = fitz.open(filepath)
chunks = []
for page_num in range(len(doc)):
page = doc[page_num]
page_text = page.get_text()
# Split into chunks with overlap
start = 0
while start < len(page_text):
end = start + chunk_size
chunk = page_text[start:end]
chunks.append({
'text': chunk,
'page': page_num + 1,
'char_start': start,
'source': filepath
})
start += chunk_size - overlap # overlap
doc.close()
return chunks
chunks = pdf_to_chunks('research_paper.pdf')
print(f'Total chunks: {len(chunks)}')
print(f'Sample: {chunks[0]["text"][:200]}')Łączenie PyMuPDF i pdfplumber
PyMuPDF służy do ekstrakcji tekstu (jest szybszy), a pdfplumber do wykrywania tabel (jest dokładniejszy). Połączony ekstraktor uruchamia obie biblioteki dla każdej strony i zwraca uporządkowaną zawartość, w której tekst i tabele są rozdzielone.
import fitz
import pdfplumber
def full_pdf_extract(filepath):
result = {'text_by_page': [], 'tables': []}
# Text extraction with PyMuPDF
doc = fitz.open(filepath)
for i in range(len(doc)):
text = extract_without_headers_footers(doc[i])
result['text_by_page'].append({'page': i + 1, 'text': text})
doc.close()
# Table extraction with pdfplumber
with pdfplumber.open(filepath) as pdf:
for page_num, page in enumerate(pdf.pages):
tables = page.extract_tables()
for t in tables:
result['tables'].append({
'page': page_num + 1,
'headers': t[0] if t else [],
'rows': t[1:] if t and len(t) > 1 else []
})
return resultZapisywanie wyodrębnionego tekstu do plików
Po wyodrębnieniu tekstu z plików PDF należy zapisać go w formacie, który mogą przetwarzać agenci używani w dalszych etapach. Pliki tekstowe sprawdzają się w potokach osadzania, a format JSON zachowuje strukturę stron potrzebną do śledzenia cytowań.
import json, os
class FakePage:
def __init__(self, text): self.text = text
def get_text(self): return self.text
class FakeDoc(list):
def close(self): pass
def fitz_open(path):
return FakeDoc([FakePage('Page 1 text'), FakePage('Page 2 text')])
def pdf_to_text_file(pdf_path, output_dir):
doc = fitz_open(pdf_path)
base = os.path.splitext(os.path.basename(pdf_path))[0]
txt_path = os.path.join(output_dir, base + '.txt')
with open(txt_path, 'w', encoding='utf-8') as f:
for i, page in enumerate(doc):
f.write(f'--- Page {i+1} ---\n{page.get_text()}\n')
json_path = os.path.join(output_dir, base + '.json')
pages = [{'page': i+1, 'text': p.get_text()} for i, p in enumerate(doc)]
with open(json_path, 'w') as f:
json.dump({'source': pdf_path, 'pages': pages}, f, indent=2)
doc.close()
print(f'Saved: {txt_path} and {json_path}')
return txt_path, json_path
pdf_to_text_file('sample.pdf', '.')Sprawdzenie wiedzy
Which Python library is best suited for extracting tables from PDF files?
Podsumowanie: przetwarzanie plików PDF za pomocą PyMuPDF i pdfplumber
PyMuPDF (fitz) to szybki wybór do ekstrakcji tekstu i metadanych oraz obsługi układu wielokolumnowego. pdfplumber doskonale sprawdza się przy ekstrakcji tabel dzięki konfigurowalnym strategiom geometrycznym.
Najważniejsze techniki: używanie get_text('blocks') do ekstrakcji uwzględniającej położenie, odfiltrowywanie nagłówków i stopek na podstawie ich pozycji w pionie, obsługa układów wielokolumnowych przez sortowanie bloków według kolumn oraz dzielenie tekstu na nakładające się fragmenty na potrzeby systemów pobierania informacji przez agentów. Najlepsze rezultaty daje połączenie obu bibliotek.
Ucz się AI Agents dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 60
- Lekcje
- 239
Często zadawane pytania
Czy lekcja „Parsowanie PDF za pomocą PyMuPDF i pdfplumber” jest bezpłatna?
Tak — pełny tekst „Parsowanie PDF za pomocą PyMuPDF i pdfplumber” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Agents, przejdź na CoddyKit PRO. Kurs AI Agents zawiera 4 lekcji w sumie.
Co nauczysz się w „Parsowanie PDF za pomocą PyMuPDF i pdfplumber”?
Programowe wyodrębnianie tekstu, tabel i metadanych z plików PDF. Ćwiczysz AI Agents z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć AI Agents?
Nie wymagamy żadnego doświadczenia. AI Agents w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Parsowanie PDF za pomocą PyMuPDF i pdfplumber”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji AI Agents?
Tak. Każda lekcja AI Agents zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Parsowanie PDF za pomocą PyMuPDF i pdfplumber
- OCR dla skanowanych dokumentów
- Agenci pytań i odpowiedzi dla wielu dokumentów
- Klasyfikacja i routing dokumentów