AI Agents · Lekcja

Parsowanie PDF za pomocą PyMuPDF i pdfplumber

Programowe wyodrębnianie tekstu, tabel i metadanych z plików PDF.

Lekcja 1 z 413 kroki

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_text

Filtrowanie 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 result

Zapisywanie 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.

Bezpłatny start

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

  1. Parsowanie PDF za pomocą PyMuPDF i pdfplumber
  2. OCR dla skanowanych dokumentów
  3. Agenci pytań i odpowiedzi dla wielu dokumentów
  4. Klasyfikacja i routing dokumentów
← Powrót do AI Agents