Streszczenie
  • Instalacja biblioteki pypdf
  • Wycinanie wybranych stron z PDF
  • Wycinanie zakresu stron PDF
  • Dzielenie PDF na rozdziały
Rozdzielanie i scalanie stron PDF w Pythonie

Rozdzielanie i scalanie stron PDF w Pythonie

Rozdzielanie i scalanie stron PDF w Pythonie pozwala precyzyjnie zarządzać dużymi dokumentami bez ręcznej pracy w edytorach PDF. Możesz wycinać konkretne strony, dzielić dokumenty na rozdziały, tworzyć osobne pliki z każdej strony, łączyć wybrane fragmenty z wielu PDF-ów i obracać strony w finalnym dokumencie.

To przydatne w pracy z raportami, umowami, skanami, dokumentacją projektową, materiałami szkoleniowymi i dużymi plikami archiwalnymi. Zamiast ręcznie wybierać strony i zapisywać nowe dokumenty, możesz przygotować skrypt, który zrobi to automatycznie i powtarzalnie.

Do takich operacji najlepiej sprawdza się biblioteka pypdf, która pozwala czytać pliki PDF, wybierać strony, zapisywać nowe dokumenty i manipulować stronami bez utraty jakości oryginalnego pliku.

Kurs · 24 lekcje8h 14m
Kurs

Kurs Python od podstaw — PyStart

Zacznij programować w Pythonie od zera. Praktyczny kurs wideo z ćwiczeniami — bez wcześniejszego doświadczenia.

  • 24 lekcje wideo + 80 ćwiczeń
  • Realne bazy z e-commerce
  • Społeczność i code-review
699 zł
Zacznij kurs Pythona

Instalacja biblioteki pypdf

Najpierw zainstaluj bibliotekę pypdf:

Bash
1 pip install pypdf

W starszych materiałach możesz spotkać bibliotekę PyPDF2. W nowych projektach lepiej używać pypdf, ponieważ jest aktualnym i wygodnym narzędziem do pracy z plikami PDF w Pythonie.

Wycinanie wybranych stron z PDF

Najprostszy przypadek to wyciągnięcie kilku konkretnych stron z większego dokumentu. W pypdf strony są indeksowane od zera, czyli pierwsza strona ma indeks 0.

Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 from pypdf import PdfReader, PdfWriter def extract_pages(input_pdf: str, output_pdf: str, pages: list[int]): """Wycina wybrane strony z dokumentu PDF. pages: lista indeksów stron liczonych od 0. """ reader = PdfReader(input_pdf) writer = PdfWriter() total_pages = len(reader.pages) for page_num in pages: if 0 <= page_num < total_pages: writer.add_page(reader.pages[page_num]) else: print( f"Ostrzeżenie: strona {page_num + 1} nie istnieje. " f"Dokument ma {total_pages} stron." ) with open(output_pdf, "wb") as output_file: writer.write(output_file) print(f"Wycięto strony {pages} do pliku: {output_pdf}") # Przykład: strony 1, 3 i 5, czyli indeksy 0, 2, 4 extract_pages("dokument.pdf", "wyciete_strony.pdf", [0, 2, 4])

Taki skrypt przydaje się, gdy chcesz szybko utworzyć nowy dokument z wybranych stron, np. samego podsumowania, aneksu albo wybranych załączników.

Wycinanie zakresu stron PDF

W praktyce częściej wycina się ciągły zakres stron, np. od strony 5 do 10. Dla wygody użytkownika funkcja może przyjmować numerację od 1, czyli taką samą jak w większości programów do czytania PDF.

Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 from pypdf import PdfReader, PdfWriter def extract_page_range( input_pdf: str, output_pdf: str, start_page: int, end_page: int ): """Wycina zakres stron z dokumentu PDF. start_page i end_page są liczone od 1. """ reader = PdfReader(input_pdf) writer = PdfWriter() total_pages = len(reader.pages) if start_page < 1: raise ValueError("start_page musi być większe lub równe 1.") if end_page < start_page: raise ValueError("end_page nie może być mniejsze niż start_page.") start_index = start_page - 1 end_index = min(end_page, total_pages) for page_index in range(start_index, end_index): writer.add_page(reader.pages[page_index]) with open(output_pdf, "wb") as output_file: writer.write(output_file) print(f"Wycięto strony {start_page}-{end_index} do: {output_pdf}") extract_page_range("dokument.pdf", "strony_5_10.pdf", 5, 10)

Ten wzorzec jest dobry do wycinania rozdziałów, sekcji raportu, części umowy albo określonych zakresów z dokumentacji.

Dzielenie PDF na rozdziały

Duże dokumenty często trzeba podzielić na logiczne części. Możesz zdefiniować rozdziały w słowniku i automatycznie zapisać każdy zakres stron jako osobny plik PDF.

Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 from pathlib import Path from pypdf import PdfReader, PdfWriter def split_pdf_by_chapters(input_pdf: str, chapters: dict[str, tuple[int, int]]): """Dzieli dokument PDF na rozdziały. chapters: { "wstep": (1, 10), "rozdzial_1": (11, 50) } """ reader = PdfReader(input_pdf) total_pages = len(reader.pages) base_name = Path(input_pdf).stem for chapter_name, (start_page, end_page) in chapters.items(): writer = PdfWriter() start_index = start_page - 1 end_index = min(end_page, total_pages) if start_index < 0 or start_index >= total_pages: print(f"Pominięto rozdział {chapter_name}: niepoprawny początek.") continue for page_index in range(start_index, end_index): writer.add_page(reader.pages[page_index]) output_file = f"{base_name}_{chapter_name}.pdf" with open(output_file, "wb") as file: writer.write(file) print(f"Utworzono: {output_file} — strony {start_page}-{end_index}") split_pdf_by_chapters( "ksiazka.pdf", { "wstep": (1, 10), "rozdzial_1": (11, 50), "rozdzial_2": (51, 100), "zakonczenie": (101, 120) } )

To szczególnie przydatne przy książkach, raportach rocznych, dokumentacji technicznej, materiałach szkoleniowych i dużych plikach składających się z wielu sekcji.

Dzielenie każdej strony na osobny plik

Kurs · 24 lekcje8h 14m
Kurs

Kurs Python dla początkujących — PyStart

Zacznij programować w Pythonie! Idealne dla osób bez doświadczenia. Praktyczne zadania, projekty i wsparcie społeczności.

  • 24 lekcje wideo + 80 ćwiczeń
  • Realne bazy z e-commerce
  • Społeczność i code-review
699 zł
Rozpocznij naukę

Czasem potrzebujesz zapisać każdą stronę PDF jako osobny dokument. Taki proces przydaje się przy skanach, formularzach, archiwizacji albo dalszym przetwarzaniu pojedynczych stron.

Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from pathlib import Path from pypdf import PdfReader, PdfWriter def split_every_page(input_pdf: str, output_dir: str): """Dzieli dokument PDF na pojedyncze strony.""" reader = PdfReader(input_pdf) base_name = Path(input_pdf).stem output_path = Path(output_dir) output_path.mkdir(parents=True, exist_ok=True) for page_number, page in enumerate(reader.pages, start=1): writer = PdfWriter() writer.add_page(page) output_file = output_path / f"{base_name}_strona_{page_number:03d}.pdf" with open(output_file, "wb") as file: writer.write(file) print(f"Podzielono {len(reader.pages)} stron do katalogu: {output_dir}") split_every_page("dokument.pdf", "strony")

Nazwy z numerami 001, 002, 003 pomagają zachować poprawną kolejność plików w folderze.

Łączenie stron z różnych plików PDF

Najbardziej elastyczny scenariusz to stworzenie nowego dokumentu z wybranych stron pochodzących z różnych źródeł. Możesz np. wziąć stronę tytułową z jednego pliku, rozdział z drugiego i załączniki z trzeciego.

Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 from pypdf import PdfReader, PdfWriter def merge_pages_from_sources(sources: list[dict], output_pdf: str): """Łączy wybrane strony z różnych plików PDF. Przykład sources: [ {"file": "dok1.pdf", "pages": [1, 2, 3]}, {"file": "dok2.pdf", "pages": (1, 5)}, {"file": "dok3.pdf", "pages": None} ] pages: - lista oznacza konkretne strony liczone od 1, - krotka oznacza zakres stron od-do liczony od 1, - None oznacza wszystkie strony. """ writer = PdfWriter() for source in sources: file_path = source["file"] pages = source.get("pages") reader = PdfReader(file_path) total_pages = len(reader.pages) if pages is None: for page in reader.pages: writer.add_page(page) elif isinstance(pages, tuple): start_page, end_page = pages start_index = start_page - 1 end_index = min(end_page, total_pages) for page_index in range(start_index, end_index): writer.add_page(reader.pages[page_index]) else: for page_number in pages: page_index = page_number - 1 if 0 <= page_index < total_pages: writer.add_page(reader.pages[page_index]) else: print(f"Pominięto stronę {page_number} z pliku {file_path}") with open(output_pdf, "wb") as file: writer.write(file) print(f"Połączono strony z {len(sources)} źródeł do: {output_pdf}") merge_pages_from_sources( [ {"file": "dok1.pdf", "pages": [1, 2, 3]}, {"file": "dok2.pdf", "pages": (1, 5)}, {"file": "dok3.pdf", "pages": None} ], "polaczony_dokument.pdf" )

To dobry sposób na tworzenie spersonalizowanych raportów, pakietów dokumentów, ofert albo zestawów materiałów dla konkretnych odbiorców.

Rotacja stron PDF

Newsletter · co środę

Python co tydzień — newsletter dla programistów

Otrzymuj codzienne ćwiczenia, ciekawostki z ekosystemu Pythona i wskazówki do rozmów rekrutacyjnych.

2 312 czytelników · ⭐ 4,8

Niektóre dokumenty mają strony obrócone w złym kierunku. pypdf pozwala obracać strony o 90, 180 lub 270 stopni.

Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from pypdf import PdfReader, PdfWriter def rotate_pages( input_pdf: str, output_pdf: str, pages: list[int], rotation: int = 90 ): """Obraca wybrane strony PDF. pages: numery stron liczone od 1. rotation: 90, 180 lub 270. """ if rotation not in [90, 180, 270]: raise ValueError("rotation musi wynosić 90, 180 albo 270.") reader = PdfReader(input_pdf) writer = PdfWriter() pages_to_rotate = set(pages) for page_number, page in enumerate(reader.pages, start=1): if page_number in pages_to_rotate: page.rotate(rotation) writer.add_page(page) with open(output_pdf, "wb") as file: writer.write(file) print(f"Obrócono strony {pages} o {rotation}° i zapisano do: {output_pdf}") rotate_pages("dokument.pdf", "obrocone_strony.pdf", [1, 2, 3], rotation=90)

Taki skrypt pozwala poprawić orientację wybranych stron bez modyfikowania reszty dokumentu.

Wycinanie i rotacja w jednym procesie

Możesz połączyć kilka operacji w jednej funkcji: wyciąć wybrane strony i od razu je obrócić.

Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from pypdf import PdfReader, PdfWriter def extract_and_rotate( input_pdf: str, output_pdf: str, pages: list[int], rotation: int = 90 ): """Wycina wybrane strony i obraca je w nowym dokumencie. pages: numery stron liczone od 1. """ reader = PdfReader(input_pdf) writer = PdfWriter() for page_number in pages: page_index = page_number - 1 if 0 <= page_index < len(reader.pages): page = reader.pages[page_index] page.rotate(rotation) writer.add_page(page) else: print(f"Pominięto nieistniejącą stronę: {page_number}") with open(output_pdf, "wb") as file: writer.write(file) print(f"Wycięto i obrócono strony {pages} do: {output_pdf}") extract_and_rotate("dokument.pdf", "wyciete_i_obrocone.pdf", [1, 2, 3], 90)

To przydatne, gdy z dużego dokumentu chcesz utworzyć mniejszy, poprawnie ustawiony plik wynikowy.

Bezpieczna obsługa błędów przy pracy z PDF

W automatyzacji dokumentów trzeba przewidzieć uszkodzone pliki, złe ścieżki, błędne zakresy stron i zaszyfrowane PDF-y. Poniższy przykład pokazuje bezpieczne wycinanie zakresu stron.

Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 from pathlib import Path from pypdf import PdfReader, PdfWriter def safe_extract_page_range( input_pdf: str, output_pdf: str, start_page: int, end_page: int ) -> bool: """Bezpiecznie wycina zakres stron z obsługą błędów.""" input_path = Path(input_pdf) if not input_path.exists(): print(f"Plik nie istnieje: {input_pdf}") return False try: reader = PdfReader(str(input_path)) if reader.is_encrypted: print(f"Plik jest zaszyfrowany: {input_pdf}") return False total_pages = len(reader.pages) if start_page < 1 or end_page < start_page: print("Niepoprawny zakres stron.") return False writer = PdfWriter() for page_index in range(start_page - 1, min(end_page, total_pages)): writer.add_page(reader.pages[page_index]) with open(output_pdf, "wb") as file: writer.write(file) print(f"Zapisano: {output_pdf}") return True except Exception as error: print(f"Błąd przetwarzania PDF: {error}") return False safe_extract_page_range("dokument.pdf", "zakres.pdf", 2, 8)

Taki kod lepiej nadaje się do codziennego użycia niż minimalne przykłady bez walidacji.

Dobre praktyki przy rozdzielaniu i scalaniu PDF

Przy automatyzacji pracy ze stronami PDF warto trzymać się kilku zasad:

  • zawsze sprawdzaj, czy plik wejściowy istnieje,
  • pamiętaj, czy funkcja używa numeracji od 0 czy od 1,
  • zapisuj wynik do osobnego katalogu,
  • nie nadpisuj oryginalnych dokumentów,
  • waliduj zakresy stron przed zapisem,
  • dodawaj czytelne nazwy plików wynikowych,
  • przy dużych dokumentach loguj liczbę przetworzonych stron,
  • pomijaj lub raportuj zaszyfrowane PDF-y,
  • testuj skrypt na kopii dokumentu,
  • stosuj pathlib do pracy ze ścieżkami.

Dzięki temu skrypty są bezpieczniejsze i łatwiejsze do utrzymania.

Podsumowanie

Rozdzielanie i scalanie stron PDF w Pythonie pozwala tworzyć elastyczne procesy automatyzacji dokumentów. Za pomocą pypdf możesz wycinać pojedyncze strony, zakresy, rozdziały, zapisywać każdą stronę osobno, obracać strony i budować nowe dokumenty z fragmentów wielu plików.

Najważniejsze jest dobre zarządzanie numeracją stron, walidacja zakresów i bezpieczny zapis wyników. Dzięki temu skrypty mogą obsługiwać nie tylko pojedyncze pliki, ale też powtarzalne procesy w pracy biurowej, raportowej i archiwalnej.

Jeśli chcesz zacząć praktycznie, przygotuj jeden duży PDF i napisz trzy funkcje: wycinanie zakresu stron, podział na pojedyncze strony i scalanie wybranych stron z kilku dokumentów. To fundament większości automatyzacji PDF w Pythonie.

➡️ Następny artykuł

Po opanowaniu operacji na stronach PDF naucz się konwertować pliki do i z formatu PDF:

Konwersja plików do PDF i z PDF w Pythonie — generowanie PDF z tekstu, obrazów i CSV oraz ekstrakcja tekstu z dokumentów PDF dla dalszego przetwarzania.

Część 16 z 26

Tworzenie spisu treści i łączenie rozdziałów w PDF

druga lekcja cyklu „Automatyzacja procesów z n8n — od danych do AI w jednym narzędziu"

Czytaj kolejny →