Excel e documentos de trabalho

Combine PDFs e extraia um intervalo de páginas com pypdf

Combine vários PDFs em um único arquivo, extraia um intervalo inclusivo de páginas para um segundo arquivo e verifique a contagem e a ordem das páginas resultantes. Um conjunto sintético de páginas em branco com dimensões deliberadamente diferentes torna o resultado verificável manualmente.

Ver o sumário

A tradução foi feita com IA. Confira o código, as unidades e os valores junto com o original. A revisão por falantes nativos de cada idioma ainda não foi concluída. English

Para quem éEste guia é voltado a pessoas que precisam combinar PDFs ou extrair páginas selecionadas sem modificar os documentos originais.

Preparação
  • Python 3.12 e um comando de terminal que inicie essa versão.
  • pypdf instalado com python -m pip install pypdf.
  • Uma pasta de trabalho em que os scripts possam criar pastas dentro de outputs.
  • Espaço em disco suficiente para os source PDFs, merged PDF e extracted PDF.

01Defina as regras de combinação e extração

O workflow usa três source PDFs em uma ordem explícita: alpha.pdf, beta.pdf e depois gamma.pdf. Suas pages são adicionadas a um único merged PDF. Um segundo output extrai então as pages 2 through 5 do merged PDF, usando a numeração humana comum em que a primeira página é page 1.

Python sequences usam zero-based indexes, mas este script aceita START_PAGE e END_PAGE como one-based inclusive page numbers. Portanto, pages 2 through 5 correspondem às Python slice positions 1 through 4, implementadas como merged_reader.pages[START_PAGE - 1:END_PAGE].

02Crie três PDFs sintéticos

Os PDFs abaixo são sintéticos e foram criados especificamente para este artigo. Cada page está em branco, mas cada uma tem width e height diferentes. Isso torna o page order verificável de forma independente, sem exigir outro PDF-generation package.

python
from pathlib import Path
from pypdf import PdfWriter

SOURCE_DIR = Path("outputs") / "pdf_merge_split_demo"
PDFS = {
    "alpha.pdf": [(100, 200), (110, 210)],
    "beta.pdf": [(120, 220)],
    "gamma.pdf": [(130, 230), (140, 240), (150, 250)],
}

SOURCE_DIR.parent.mkdir(parents=True, exist_ok=True)
SOURCE_DIR.mkdir()  # Stop if the synthetic source already exists.

for filename, page_sizes in PDFS.items():
    writer = PdfWriter()
    for width, height in page_sizes:
        writer.add_blank_page(width=width, height=height)
    target = SOURCE_DIR / filename
    with target.open("xb") as stream:
        writer.write(stream)
text
python create_pdf_demo.py
Source PDFPagesDimensões das páginas em ordem
alpha.pdf2100×200, 110×210
beta.pdf1120×220
gamma.pdf3130×230, 140×240, 150×250

Os três source files contêm 6 pages no total: 2 + 1 + 3. As dimensions são expressas em PDF user-space units. Sua finalidade aqui é apenas dar a cada synthetic page uma signature reconhecível.

03Determine a ordem esperada das páginas

Como os inputs são listados explicitamente, o merged PDF deve conter primeiro as duas pages de alpha, seguidas pela page de beta e depois pelas três pages de gamma. O merged result deve, portanto, conter 6 pages.

Merged pageSourceDimensões esperadas
1alpha.pdf page 1100×200
2alpha.pdf page 2110×210
3beta.pdf page 1120×220
4gamma.pdf page 1130×230
5gamma.pdf page 2140×240
6gamma.pdf page 3150×250

Portanto, extrair as merged pages 2 through 5 deve produzir exatamente 4 pages com dimensions 110×210, 120×220, 130×230 e 140×240 nessa ordem.

04Combine os arquivos e extraia as pages 2 through 5

Salve o script a seguir como pdf_merge_split.py. Ele valida cada input file, rejeita encrypted PDFs neste exemplo simples, combina todas as pages, reabre o merged output para verificá-lo e depois cria o page-range file solicitado.

python
from pathlib import Path
from pypdf import PdfReader, PdfWriter

SOURCE_DIR = Path("outputs") / "pdf_merge_split_demo"
INPUTS = ("alpha.pdf", "beta.pdf", "gamma.pdf")
OUTPUT_DIR = Path("outputs") / "pdf_merge_split_result"
MERGED = OUTPUT_DIR / "merged.pdf"
EXTRACTED = OUTPUT_DIR / "pages_2_to_5.pdf"
START_PAGE = 2
END_PAGE = 5


def page_size(page) -> tuple[int, int]:
    width = int(float(page.mediabox.width))
    height = int(float(page.mediabox.height))
    return width, height


def main() -> None:
    source_root = SOURCE_DIR.resolve(strict=True)
    if not source_root.is_dir():
        raise ValueError("SOURCE_DIR must be a directory.")
    if START_PAGE < 1 or END_PAGE < START_PAGE:
        raise ValueError("Invalid page range.")

    input_paths = [source_root / name for name in INPUTS]
    for path in input_paths:
        if not path.is_file():
            raise FileNotFoundError(f"Missing input PDF: {path}")

    OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
    OUTPUT_DIR.mkdir()  # Refuse to reuse an existing result folder.

    expected_sizes = []
    writer = PdfWriter()
    for path in input_paths:
        reader = PdfReader(path)
        if reader.is_encrypted:
            raise ValueError(f"Encrypted PDF is not supported here: {path.name}")
        for page in reader.pages:
            expected_sizes.append(page_size(page))
            writer.add_page(page)

    with MERGED.open("xb") as stream:
        writer.write(stream)

    merged_reader = PdfReader(MERGED)
    if merged_reader.is_encrypted:
        raise RuntimeError("Unexpected encrypted merged PDF.")
    merged_sizes = [page_size(page) for page in merged_reader.pages]
    if merged_sizes != expected_sizes:
        raise RuntimeError("Merged page count or order does not match the inputs.")

    if END_PAGE > len(merged_reader.pages):
        raise ValueError(
            f"Requested page {END_PAGE}, but merged PDF has only "
            f"{len(merged_reader.pages)} pages."
        )

    selected_pages = merged_reader.pages[START_PAGE - 1:END_PAGE]
    extracted_writer = PdfWriter()
    expected_extract_sizes = []
    for page in selected_pages:
        expected_extract_sizes.append(page_size(page))
        extracted_writer.add_page(page)

    with EXTRACTED.open("xb") as stream:
        extracted_writer.write(stream)

    extracted_reader = PdfReader(EXTRACTED)
    extracted_sizes = [page_size(page) for page in extracted_reader.pages]
    if extracted_sizes != expected_extract_sizes:
        raise RuntimeError("Extracted PDF does not match the selected pages.")

    print(f"Merged {len(INPUTS)} PDFs into {len(merged_reader.pages)} pages.")
    print(
        f"Extracted pages {START_PAGE}-{END_PAGE}: "
        f"{len(extracted_reader.pages)} pages."
    )
    print(f"Merged output: {MERGED.as_posix()}")
    print(f"Extracted output: {EXTRACTED.as_posix()}")


if __name__ == "__main__":
    main()
text
python pdf_merge_split.py

05Compare os outputs esperados

O primeiro output, merged.pdf, deve conter 6 pages. O segundo output, pages_2_to_5.pdf, deve conter 4 pages. A extração é inclusiva nas duas extremidades porque o script converte os human page numbers no Python slice correspondente.

OutputPages esperadasDimensões esperadas em ordem
merged.pdf6100×200, 110×210, 120×220, 130×230, 140×240, 150×250
pages_2_to_5.pdf4110×210, 120×220, 130×230, 140×240

O console text esperado abaixo foi derivado manualmente a partir dos synthetic inputs e do código. Não é um execution log.

text
Merged 3 PDFs into 6 pages.
Extracted pages 2-5: 4 pages.
Merged output: outputs/pdf_merge_split_result/merged.pdf
Extracted output: outputs/pdf_merge_split_result/pages_2_to_5.pdf

06Verifique o resultado antes de usar PDFs reais

  1. Abra merged.pdf e confirme que ele tem 6 pages.
  2. Abra pages_2_to_5.pdf e confirme que ele tem exatamente 4 pages.
  3. Inspecione page dimensions ou outra visible page feature para confirmar que a ordem é 110×210, 120×220, 130×230, 140×240 no arquivo extraído.
  4. Confirme que alpha.pdf, beta.pdf e gamma.pdf ainda existem inalterados na source folder.
  5. Execute o script novamente sem alterar OUTPUT_DIR. Ele deve parar com FileExistsError em vez de substituir os PDFs anteriores.

Para documents reais, também inspecione visualmente o page content. Matching counts por si só não revelam todos os possíveis problemas, como um input order inesperado ou um source PDF cujos page labels diferem das physical page positions.

07Reconheça erros comuns

SintomaO que verificar
ModuleNotFoundError: No module named pypdfInstale pypdf no mesmo Python environment com python -m pip install pypdf.
FileNotFoundErrorVerifique SOURCE_DIR, INPUTS e o working directory do terminal. Neste exemplo, execute primeiro o synthetic setup script.
FileExistsErrorA result folder já existe. Revise os outputs anteriores e escolha uma nova folder em vez de sobrescrevê-los.
Encrypted PDF is not supported hereUse uma decrypted copy permitida ou adicione um password-handling workflow explícito e adequado aos seus documents.
Requested page is beyond the merged PDFVerifique o merged page count e os valores one-based START_PAGE e END_PAGE.
Merged or extracted verification mismatchTrate o generated file como unverified. Verifique os inputs e use uma nova output folder na próxima execução.

Se uma exception ocorrer depois que OUTPUT_DIR for criado, partial files podem permanecer. O script não os exclui automaticamente. Mantenha failed outputs separados de verified files.

08Entenda os limites

Este workflow verifica physical page count e page dimensions, não semantic content. Ele não compara rendered pixels, extracted text, annotations, forms, bookmarks, named destinations, attachments, signatures ou accessibility structure.

PDF page labels podem diferir das physical page positions. Um document pode exibir roman numerals ou custom labels mesmo que pypdf continue acessando seus page objects por zero-based sequence position. Os valores START_PAGE e END_PAGE neste tutorial se referem a physical sequence positions, não a printed page numbers.

Alguns PDFs complexos contêm interactive forms, digital signatures, encrypted content, unusual object relationships ou features que exigem tratamento mais cuidadoso. Combinar um digitally signed PDF em um novo document não preserva o significado da signature original como uma assinatura sobre o file recém-criado. Para records importantes, inspecione os PDF requirements relevantes antes de tratar uma merged copy como equivalente ao original.

Registro de execução e verificação

2026-09-20 · exemplo verificado manualmente · alvo: Python 3.12 · pypdf necessário · sem execução

  • Foram contados manualmente os source page totals de 2, 1 e 3, resultando em 6 merged pages.
  • Foram rastreadas manualmente as merged dimensions esperadas como 100x200, 110x210, 120x220, 130x230, 140x240 e 150x250.
  • O human page range inclusivo 2-5 foi convertido manualmente para as Python positions 1 through 4 e foi confirmado que contém 4 pages.
  • Foram derivadas manualmente as extracted dimensions como 110x210, 120x220, 130x230 e 140x240.
  • O código foi inspecionado para confirmar que os source PDFs são abertos para leitura, os outputs vão para uma pasta separada e uma output folder existente faz a execução parar.
  • Foram inspecionadas a lógica de comparação de page-count e page-dimension e a saída esperada do console foi derivada manualmente.
Limites da verificação
  • O código não foi executado pelo autor desta resposta; nenhum PDF file foi criado, combinado, extraído ou aberto aqui.
  • Encrypted PDFs, forms, annotations, bookmarks, digital signatures, attachments, page labels e malformed PDFs não foram testados.
  • As page-dimension checks verificam a ordem no exemplo sintético, mas não provam semantic equivalence para PDFs reais arbitrários.
  • As URLs da documentação oficial foram fornecidas com base em locais de documentação conhecidos, mas não foram verificadas ao vivo.

Princípios de redação e verificação de todo o site

Fontes de referência

As explicações e os exemplos são de elaboração própria. Os comportamentos e conceitos relacionados podem ser consultados nas fontes oficiais abaixo.