Cykl: Automatyzacja procesów z n8n — od danych do AI w jednym narzędziu · Część 7/26

Łączenie plików PDF w jeden plik w Pythonie

Kacper Sieradziński
Kacper Sieradziński18 stycznia 2025 · 4 min czytania
Streszczenie
  • Instalacja biblioteki pypdf
  • Podstawowe łączenie plików PDF
  • Łączenie wszystkich PDF z katalogu
  • Sortowanie plików przed scaleniem
Łączenie plików PDF w jeden plik w Pythonie

Łączenie plików PDF w jeden plik w Pythonie

Łączenie plików PDF w jeden dokument to jedna z najczęstszych automatyzacji biurowych. Przydaje się przy raportach, fakturach, umowach, dokumentacji projektowej, skanach, załącznikach do maili i materiałach archiwalnych. Zamiast ręcznie scalać pliki w edytorze PDF, możesz przygotować prosty skrypt w Pythonie, który zrobi to automatycznie, powtarzalnie i bez pomyłek w kolejności dokumentów.

Do łączenia PDF w Pythonie najlepiej sprawdza się biblioteka pypdf, czyli następca popularnego PyPDF2. Pozwala scalać wiele dokumentów, wybierać konkretne strony, ustawiać metadane, przetwarzać całe katalogi i obsługiwać błędy przy uszkodzonych plikach.

W tym artykule zobaczysz praktyczne przykłady: podstawowe łączenie PDF, batch merge z katalogu, sortowanie plików, wybór stron, ustawianie metadanych oraz bezpieczne scalanie z obsługą błędów.

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
499 zł799 zł−38%
Zacznij kurs Pythona

Instalacja biblioteki pypdf

Najpierw zainstaluj bibliotekę pypdf:

Bash
1 pip install pypdf

W starszych projektach możesz spotkać PyPDF2, ale w nowych skryptach lepiej używać pypdf. Ma podobny sposób działania, ale jest aktualniej rozwijany i wygodny w codziennej automatyzacji dokumentów.

Podstawowe łączenie plików PDF

Najprostszy przypadek to połączenie kilku znanych plików PDF w jeden dokument. Wystarczy utworzyć obiekt PdfMerger, dodać pliki przez append(), a potem zapisać wynik.

Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from pypdf import PdfMerger def merge_pdfs(pdf_files: list[str], output_path: str): """Łączy wiele plików PDF w jeden dokument.""" merger = PdfMerger() for pdf_file in pdf_files: merger.append(pdf_file) merger.write(output_path) merger.close() print(f"Połączono {len(pdf_files)} plików PDF w: {output_path}") pdf_files = [ "dokument1.pdf", "dokument2.pdf", "dokument3.pdf" ] merge_pdfs(pdf_files, "polaczony_dokument.pdf")

Kolejność plików na liście ma znaczenie. Jeśli jako pierwszy podasz dokument1.pdf, jego strony znajdą się na początku wynikowego dokumentu.

Łączenie wszystkich PDF z katalogu

W praktyce często chcesz połączyć wszystkie pliki PDF znajdujące się w jednym folderze. Można to zrobić za pomocą pathlib, który ułatwia pracę ze ścieżkami.

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 pathlib import Path from pypdf import PdfMerger def batch_merge_pdfs(directory: str, output_path: str): """Łączy wszystkie pliki PDF z katalogu w kolejności alfabetycznej.""" pdf_dir = Path(directory) if not pdf_dir.exists(): raise FileNotFoundError(f"Katalog nie istnieje: {directory}") pdf_files = sorted(pdf_dir.glob("*.pdf")) if not pdf_files: print("Nie znaleziono plików PDF w katalogu.") return merger = PdfMerger() for pdf_file in pdf_files: print(f"Dodawanie: {pdf_file.name}") merger.append(str(pdf_file)) merger.write(output_path) merger.close() print(f"Połączono {len(pdf_files)} plików PDF w: {output_path}") batch_merge_pdfs("./pliki_pdf", "wszystkie_dokumenty.pdf")

To dobre rozwiązanie, gdy codziennie lub co tydzień dostajesz zestaw dokumentów do połączenia, np. faktury, raporty albo załączniki.

Sortowanie plików przed scaleniem

Sortowanie jest ważne, bo od niego zależy kolejność stron w końcowym PDF. Jeśli pliki nazywają się 1.pdf, 2.pdf, 10.pdf, zwykłe sortowanie alfabetyczne może dać kolejność 1.pdf, 10.pdf, 2.pdf.

Najlepiej nazywać pliki z zerami na początku:

1 2 3 001_wstep.pdf 002_rozdzial.pdf 003_zalaczniki.pdf

Możesz też dodać sortowanie naturalne:

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 import re from pathlib import Path from pypdf import PdfMerger def natural_sort_key(path: Path): """Sortuje nazwy z liczbami w bardziej naturalnej kolejności.""" return [ int(part) if part.isdigit() else part.lower() for part in re.split(r"(\d+)", path.name) ] def batch_merge_pdfs_natural_sort(directory: str, output_path: str): pdf_dir = Path(directory) pdf_files = sorted(pdf_dir.glob("*.pdf"), key=natural_sort_key) if not pdf_files: print("Nie znaleziono plików PDF.") return merger = PdfMerger() for pdf_file in pdf_files: print(f"Dodawanie: {pdf_file.name}") merger.append(str(pdf_file)) merger.write(output_path) merger.close() print(f"Utworzono plik: {output_path}") batch_merge_pdfs_natural_sort("./pliki_pdf", "polaczony.pdf")

Dzięki temu pliki 1.pdf, 2.pdf10.pdf zostaną połączone w logicznej kolejności.

Łączenie PDF z ustawieniem metadanych

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
499 zł799 zł−38%
Rozpocznij naukę

PDF może zawierać metadane, takie jak tytuł, autor, temat czy słowa kluczowe. Warto je ustawić, jeśli tworzysz raport, dokumentację lub plik do archiwum.

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 from pypdf import PdfMerger def merge_with_metadata( pdf_files: list[str], output_path: str, title: str = "Połączony dokument", author: str = "Automatyzacja Python" ): """Łączy pliki PDF i ustawia metadane dokumentu.""" merger = PdfMerger() for pdf_file in pdf_files: merger.append(pdf_file) merger.add_metadata({ "/Title": title, "/Author": author, "/Subject": "Dokument wygenerowany automatycznie", "/Keywords": "PDF, Python, automatyzacja, scalanie" }) merger.write(output_path) merger.close() print(f"Utworzono dokument z metadanymi: {output_path}") merge_with_metadata( ["dok1.pdf", "dok2.pdf"], "raport_roczny.pdf", title="Raport roczny", author="System automatyzacji" )

Metadane ułatwiają późniejsze wyszukiwanie i porządkowanie dokumentów, szczególnie gdy pliki trafiają do archiwum, systemu DMS albo repozytorium firmowego.

Wybór konkretnych stron z plików PDF

Nie zawsze trzeba scalać całe dokumenty. Czasem potrzebujesz tylko wybranych stron: np. pierwszej strony z faktury, stron 2–5 z raportu albo załącznika z końca dokumentu.

W pypdf zakres stron jest indeksowany od zera. Oznacza to, że 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 from pypdf import PdfMerger def merge_page_ranges(output_path: str): """Łączy wybrane zakresy stron z różnych plików PDF.""" merger = PdfMerger() # Dodaje strony 1-3, czyli indeksy 0, 1, 2 merger.append("raport.pdf", pages=(0, 3)) # Dodaje strony 2-5, czyli indeksy 1, 2, 3, 4 merger.append("zalacznik.pdf", pages=(1, 5)) merger.write(output_path) merger.close() print(f"Utworzono plik: {output_path}") merge_page_ranges("wybrane_strony.pdf")

To przydatne, gdy tworzysz jeden dokument wynikowy z fragmentów kilku różnych PDF-ów.

Łączenie pojedynczych stron z różnych PDF

Jeśli chcesz wskazać konkretne strony, możesz użyć PdfReaderPdfWriter. To daje większą kontrolę niż PdfMerger.

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 merge_selected_pages(selection: dict[str, list[int]], output_path: str): """ Łączy konkretne strony z wielu plików PDF. selection: { "dokument1.pdf": [0, 2, 4], "dokument2.pdf": [1, 3] } """ writer = PdfWriter() for pdf_file, pages in selection.items(): reader = PdfReader(pdf_file) for page_number in pages: if page_number < len(reader.pages): writer.add_page(reader.pages[page_number]) else: print(f"Pominięto stronę {page_number} z pliku {pdf_file}") with open(output_path, "wb") as output_file: writer.write(output_file) print(f"Utworzono plik: {output_path}") merge_selected_pages( { "dokument1.pdf": [0, 2, 4], "dokument2.pdf": [0, 1] }, "wybrane_strony.pdf" )

Ten wzorzec sprawdza się, gdy chcesz budować dokument wynikowy z precyzyjnie wskazanych stron.

Bezpieczne łączenie PDF z obsługą błędów

W rzeczywistych folderach mogą znajdować się uszkodzone pliki, dokumenty z hasłem, puste pliki albo ścieżki, które już nie istnieją. Dobry skrypt powinien umieć pominąć problematyczny plik i kontynuować pracę.

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 from pathlib import Path from pypdf import PdfMerger def safe_merge_pdfs(pdf_files: list[str], output_path: str): """Bezpiecznie łączy pliki PDF z obsługą błędów.""" merger = PdfMerger() successful = 0 failed = [] for pdf_file in pdf_files: path = Path(pdf_file) if not path.exists(): print(f"Ostrzeżenie: plik nie istnieje: {pdf_file}") failed.append(pdf_file) continue try: merger.append(str(path)) successful += 1 print(f"Dodano: {path.name}") except Exception as error: print(f"Błąd podczas dodawania {pdf_file}: {error}") failed.append(pdf_file) if successful > 0: merger.write(output_path) print(f"Połączono {successful} plików PDF w: {output_path}") if failed: print(f"Pominięto {len(failed)} plików: {failed}") else: print("Nie udało się połączyć żadnego pliku PDF.") merger.close() safe_merge_pdfs( ["dok1.pdf", "dok2.pdf", "nieistniejacy.pdf"], "bezpieczny_merge.pdf" )

Taki kod jest lepszy do automatyzacji niż prosty przykład bez obsługi błędów, bo nie zatrzymuje całego procesu przez jeden problematyczny dokument.

Pomijanie zaszyfrowanych PDF

Niektóre pliki PDF mogą być zabezpieczone hasłem. Wtedy zwykłe scalanie może zakończyć się błędem. Możesz wcześniej sprawdzić, czy dokument jest zaszyfrowany.

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 from pathlib import Path from pypdf import PdfReader, PdfMerger def merge_skip_encrypted(directory: str, output_path: str): """Łączy pliki PDF z katalogu, pomijając zaszyfrowane dokumenty.""" pdf_dir = Path(directory) pdf_files = sorted(pdf_dir.glob("*.pdf")) merger = PdfMerger() skipped = [] for pdf_file in pdf_files: try: reader = PdfReader(str(pdf_file)) if reader.is_encrypted: print(f"Pominięto zaszyfrowany plik: {pdf_file.name}") skipped.append(pdf_file.name) continue merger.append(str(pdf_file)) print(f"Dodano: {pdf_file.name}") except Exception as error: print(f"Błąd pliku {pdf_file.name}: {error}") skipped.append(pdf_file.name) merger.write(output_path) merger.close() print(f"Utworzono: {output_path}") if skipped: print(f"Pominięte pliki: {skipped}") merge_skip_encrypted("./pliki_pdf", "polaczony_bez_zaszyfrowanych.pdf")

Jeśli znasz hasło do PDF, możesz go wcześniej odszyfrować lub otworzyć z hasłem, ale w automatyzacjach archiwalnych często lepiej takie pliki raportować i przekazać do ręcznej weryfikacji.

Dodanie zakładek do połączonego PDF

Przy większych dokumentach warto dodać zakładki, aby użytkownik łatwo przechodził do początku każdego scalonego pliku.

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 from pathlib import Path from pypdf import PdfReader, PdfWriter def merge_with_bookmarks(pdf_files: list[str], output_path: str): """Łączy PDF-y i dodaje zakładkę na początku każdego pliku.""" writer = PdfWriter() current_page = 0 for pdf_file in pdf_files: reader = PdfReader(pdf_file) file_name = Path(pdf_file).stem writer.add_outline_item(file_name, current_page) for page in reader.pages: writer.add_page(page) current_page += 1 with open(output_path, "wb") as output_file: writer.write(output_file) print(f"Utworzono PDF z zakładkami: {output_path}") merge_with_bookmarks( ["01_wstep.pdf", "02_raport.pdf", "03_zalaczniki.pdf"], "dokument_z_zakladkami.pdf" )

Zakładki są szczególnie przydatne w dokumentacji, raportach, ofertach i większych pakietach plików.

Prosty skrypt CLI do łączenia PDF

Jeśli często łączysz PDF-y, możesz przygotować prosty skrypt uruchamiany z terminala. Dzięki temu podajesz katalog wejściowy i plik wynikowy jako argumenty.

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 import argparse from pathlib import Path from pypdf import PdfMerger def merge_directory(input_dir: str, output_file: str): pdf_dir = Path(input_dir) pdf_files = sorted(pdf_dir.glob("*.pdf")) if not pdf_files: raise ValueError("Nie znaleziono plików PDF do połączenia.") merger = PdfMerger() for pdf_file in pdf_files: print(f"Dodawanie: {pdf_file.name}") merger.append(str(pdf_file)) merger.write(output_file) merger.close() print(f"Gotowe: {output_file}") def main(): parser = argparse.ArgumentParser(description="Łączenie plików PDF w jeden dokument.") parser.add_argument("input_dir", help="Katalog z plikami PDF") parser.add_argument("output_file", help="Ścieżka pliku wynikowego PDF") args = parser.parse_args() merge_directory(args.input_dir, args.output_file) if __name__ == "__main__": main()

Uruchomienie:

Bash
1 python merge_pdf.py ./pliki_pdf wynik.pdf

Taki skrypt możesz wykorzystać w codziennej pracy, harmonogramie zadań albo większym pipeline dokumentów.

Dobre praktyki przy łączeniu plików PDF

Przy automatycznym scalaniu dokumentów warto trzymać się kilku zasad:

  • zapisuj plik wynikowy poza katalogiem wejściowym,
  • sortuj pliki przed połączeniem,
  • stosuj nazwy z numerami, np. 001_, 002_, 003_,
  • sprawdzaj, czy katalog zawiera pliki PDF,
  • obsługuj błędy przy uszkodzonych dokumentach,
  • raportuj pominięte pliki,
  • nie nadpisuj oryginalnych dokumentów,
  • dodawaj metadane do pliku wynikowego,
  • przy dużych dokumentach rozważ dodanie zakładek,
  • testuj skrypt na kopii plików.

Dzięki temu automatyzacja będzie bezpieczniejsza i łatwiejsza do utrzymania.

Podsumowanie

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

Łączenie plików PDF w Pythonie jest proste dzięki bibliotece pypdf. Możesz scalać pojedyncze dokumenty, przetwarzać całe katalogi, wybierać konkretne strony, ustawiać metadane, pomijać uszkodzone pliki i dodawać zakładki do dużych dokumentów.

Najważniejsze w praktycznej automatyzacji jest nie samo append(), ale kontrola kolejności plików, obsługa błędów i bezpieczne zapisywanie wyniku. Dzięki temu skrypt nadaje się nie tylko do jednorazowego użycia, ale też do codziennego przetwarzania raportów, faktur, skanów i dokumentacji.

Jeśli chcesz zacząć od prostego rozwiązania, przygotuj folder z plikami nazwanymi 001_, 002_, 003_, a następnie uruchom batch merge z sortowaniem. To najprostszy sposób na powtarzalne i bezpieczne scalanie PDF w Pythonie.

➡️ Następny artykuł

Po opanowaniu łączenia plików PDF poznaj techniki ich rozdzielania i manipulacji stronami:

Rozdzielanie i scalanie stron PDF w Pythonie — wycinanie zakresów stron, dzielenie dokumentów na rozdziały i zaawansowane techniki organizacji dużych dokumentów PDF.

Część 8 z 26

Lista zadań i pipeline'y w Pythonie: makefile/invoke/fabric

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

Czytaj kolejny →