Habilidade PDF
Crie PDFs a partir de especificações estruturadas, construa e preencha formulários AcroForm (com verificação de layout e sobreposições visuais), extraia texto/tabelas/metadados, mescle/divida/rote/adicione marca d'água / carimbe páginas, exporte imagens de páginas, gerencie metadados e anexos, e criptografe/descriptografe — usando pypdf, reportlab e pdfplumber. Duas capacidades absorvidas estão em references/ (leia o arquivo correspondente antes dessas tarefas):
- PDFs escaneados/somente imagem e OCR (caminho rápido pymupdf, caminho de qualidade marker-pdf, scripts/extract_pymupdf.py + scripts/extract_marker.py):
references/ocr-extraction.md - Editar texto dentro de um PDF existente via prompts em linguagem natural (CLI nano-pdf):
references/nano-pdf-editing.md
Quando Usar
- Gerar um relatório, fatura ou documento de várias páginas como PDF.
- Construir um AcroForm preenchível (caixa de texto / caixa de seleção / botão de opção / menu suspenso) a partir de uma especificação JSON, verificando o layout primeiro.
- Extrair texto, tabelas (JSON/CSV), metadados ou valores de campos de formulário de um PDF.
- Mesclar, dividir, girar, extrair subconjuntos de páginas, adicionar marca d'água, carimbar texto/imagens em coordenadas, adicionar marcadores ou compactar PDFs.
- Exportar páginas como PNG para revisão visual ou para entrega ao OCR; definir/limpar metadados do documento; adicionar/extrair anexos de arquivos.
- Preencher ou achatar formulários AcroForm; criptografar ou descriptografar com senhas.
- NÃO para PDFs escaneados/somente imagem (use
references/ocr-extraction.md) e NÃO para renderização HTML-para-PDF pixel-perfeita (use um navegador headless).
Pré-requisitos
- Python 3.10+ com
pypdf,reportlab,pdfplumber:python -m pip install pypdf reportlab pdfplumber - Opcional, para rasterização de páginas (
pdf_page_image.py, renderização de sobreposição):python -m pip install pypdfium2, ou poppler'spdftoppmno PATH. Os scripts tentam primeiro pypdfium2 → pdftoppm e reportam{"rendered": false, "missing": [...]}(exit 0) quando nenhum existe. - Cada script auxiliar verifica as importações de forma lazy e imprime uma dica de instalação se uma dependência estiver faltando.
Como Executar
Todos os auxiliares ficam em scripts/ e são CLIs argparse — execute-os com a ferramenta terminal; todos suportam --help. Eles leem/escrevem JSON estritamente como UTF-8, imprimem resultados JSON para stdout e saem com código diferente de zero em caso de falha.
python scripts/pdf_create.py spec.json -o out.pdf # construir PDF a partir de espec JSON
python scripts/pdf_make_form.py formspec.json -o form.pdf # construir AcroForm preenchível a partir de espec JSON
python scripts/pdf_form_layout.py formspec.json # verificar layout do formulário ANTES de construir
python scripts/pdf_form_layout.py formspec.json --render-overlay boxes.png [--pdf form.pdf]
python scripts/pdf_read.py doc.pdf --text # texto por página (JSON)
python scripts/pdf_read.py doc.pdf --tables --csv-dir t/ # tabelas para arquivos JSON + CSV
python scripts/pdf_read.py doc.pdf --meta # metadados, tamanhos de página, flags criptografado/escaneado
python scripts/pdf_read.py form.pdf --fields # campos do formulário: nome, tipo, valor
python scripts/pdf_merge.py a.pdf b.pdf -o merged.pdf [--bookmarks]
python scripts/pdf_split.py doc.pdf --pages 1-3,7 -o part.pdf [--rotate 90]
python scripts/pdf_fill_form.py form.pdf --fields-json values.json -o filled.pdf [--flatten]
python scripts/pdf_secure.py doc.pdf --encrypt -o enc.pdf --user-password sua-senha
python scripts/pdf_secure.py enc.pdf --decrypt -o dec.pdf --password sua-senha
python scripts/pdf_watermark.py doc.pdf --stamp mark.pdf -o stamped.pdf [--under]
python scripts/pdf_stamp.py doc.pdf -o out.pdf --text "RASCUNHO" --x 150 --y 400 \
--font-size 60 --rotation 45 --opacity 0.3 --color "#cc0000" [--pages 1-3]
python scripts/pdf_stamp.py doc.pdf -o out.pdf --image sig.png --x 400 --y 60 --width 120
python scripts/pdf_page_image.py doc.pdf --pages 1-3 --dpi 150 --out-dir imgs/
python scripts/pdf_meta.py doc.pdf --set-meta --title "T" --author "A" -o out.pdf
python scripts/pdf_meta.py doc.pdf --attach data.csv -o out.pdf
python scripts/pdf_meta.py doc.pdf --list-attachments | --extract-attachments dir/
Referência Rápida
| Tarefa | Ferramenta | Comando / API |
|---|---|---|
| Criar documento (cabeçalhos, tabelas, imagens) | reportlab platypus | pdf_create.py spec.json -o out.pdf |
| Construir formulário preenchível | reportlab acroForm | pdf_make_form.py formspec.json -o form.pdf |
| Verificar layout / imagem de sobreposição | python puro + PIL | pdf_form_layout.py formspec.json [--render-overlay o.png] |
| Texto por página | pdfplumber | pdf_read.py f.pdf --text |
| Tabelas → JSON/CSV | pdfplumber | pdf_read.py f.pdf --tables |
| Metadados / tamanhos / criptografado / escaneado | pypdf + pdfplumber | pdf_read.py f.pdf --meta |
| Mesclar (+ sumário) | pypdf | pdf_merge.py a.pdf b.pdf -o m.pdf |
| Dividir / extrair / girar | pypdf | pdf_split.py f.pdf --pages 2-5 --rotate 90 |
| Listar / preencher / achatar formulário | pypdf | pdf_read.py --fields, pdf_fill_form.py |
| Criptografar / descriptografar (AES-256) | pypdf | pdf_secure.py --encrypt/--decrypt |
| Adicionar marca d'água / carimbo em página PDF | pypdf | pdf_watermark.py f.pdf --stamp w.pdf |
| Carimbar texto/imagem em coordenadas | reportlab + pypdf | pdf_stamp.py f.pdf --text "Assine aqui" --x 400 --y 60 |
| Páginas → PNG (revisão / entrega OCR) | pypdfium2 ou pdftoppm | pdf_page_image.py f.pdf --pages 1-3 --out-dir imgs/ |
| Definir/limpar metadados, anexos | pypdf | pdf_meta.py --set-meta / --attach / --extract-attachments |
| Compactar fluxos de conteúdo | pypdf | pdf_split.py f.pdf --pages 1-N --compress |
Procedimento
- Inspecione primeiro. Execute
pdf_read.py file.pdf --meta. Verifiqueencrypted(se verdadeiro, descriptografe primeiro compdf_secure.py --decrypt) elikely_scanned_pages. Se as páginas forem apenas imagem, exporte-as compdf_page_image.py --pages <escaneadas> --dpi 300 --out-dir imgs/e entregue os PNGs para a habilidadereferences/ocr-extraction.md— não relate texto vazio como "sem conteúdo". - Crie. Escreva uma especificação JSON com
write_file(elementos:heading,paragraph,table,image,pagebreak; metadados opcionaistitle/author; números de página são adicionados automaticamente) e depois executepdf_create.py. Verifique visualmente comvision_analyzeem uma imagem de página renderizada se o layout for importante. - Extraia.
--textfornece uma lista JSON de strings por página;--tablesfornece arrays de linhas por página e também pode emitir arquivos CSV. Leia os resultados comread_file; nunca examine um PDF binário diretamente. - Manipule.
pdf_merge.pyconcatena e pode adicionar um marcador por arquivo de origem;pdf_split.pylida com intervalos de páginas (base 1, ex.:1-3,5,9-), rotação em passos de 90° e--compress. Adicione marca d'água preparando um PDF de carimbo de uma página (ex.: viapdf_create.py) e sobrepondo-o compdf_watermark.py; para carimbos de uma linha ("assine aqui", RASCUNHO diagonal, etiquetas de canto) usepdf_stamp.pycom texto ou uma imagem em coordenadas explícitas. - Construa formulários. Escreva um JSON de especificação de formulário (campos com
label_box/entry_boxem pontos PDF — vejareferences/forms.md), verifique-o compdf_form_layout.pye corrija todos os problemas relatados, opcionalmente revise o PNG--render-overlaycomvision_analyze, depois construa compdf_make_form.pye confirme compdf_read.py --fields. - Preencha formulários. Liste campos (
--fields) para saber nomes e tipos exatos, escreva um JSON UTF-8 de{"FieldName": "value"}comwrite_file(caixas de seleção aceitamtrue/false; valores de opção/rádio devem corresponder às opções de exportação do campo), depoispdf_fill_form.py. Releia com--fieldspara confirmar que os valores foram aplicados. - Metadados e anexos.
pdf_meta.py --set-metaescreve Título/Autor/Assunto/Palavras-chave (DocInfo);--clear-metaos remove;--attach/--list-attachments/--extract-attachmentslidam com arquivos incorporados. - Proteja. Criptografe com senhas de usuário e proprietário distintas e AES-256. Para remover uma senha conhecida,
--decryptescreve uma cópia não criptografada. - Verifique (veja abaixo) antes de relatar sucesso.
Armadilhas
- PDFs escaneados:
extract_text()vazio mais imagens de página significa que não há camada de texto. Direcione parareferences/ocr-extraction.md; não invente texto. - Limites de achatamento:
pdf_fill_form.py --flattenusa o suporte de achatamento do pypdf, que converte aparências de widget em conteúdo de página. É confiável para campos de texto simples e caixas de seleção, mas pode perder ou renderizar incorretamente widgets exóticos (rich text, fluxos de aparência personalizados, alguns grupos de opção). Verifique a saída achatada visualmente comvision_analyze; para achatamento à prova de falhas use um renderizador externo (ex.: Ghostscript oupdftoppm+ remontagem) como fallback. - NeedAppearances: após o preenchimento, os visualizadores só renderizam valores se os fluxos de aparência existirem. O script de preenchimento define a flag
NeedAppearancesdo AcroForm para que visualizadores conformes os regenerem; alguns visualizadores mínimos a ignoram — achate se a fidelidade de exibição for importante. - Valores de formulário não latinos: os valores são armazenados corretamente (UTF-16), mas a fonte padrão do campo pode não ter glifos, então um visualizador pode mostrar espaços em branco mesmo que os dados sejam preservados na ida e volta. Verifique com
--fields, não apenas visualmente. - Expectativas de compactação:
--compressapenas desinfla fluxos de conteúdo. A economia típica é de 0–20%; não faz nada para PDFs dominados por imagens ou fluxos já compactados. Não substitui a redução de amostragem de imagens (território do Ghostscript). - Flags de permissão não impõem: os bits de permissão da senha do proprietário (sem impressão, sem cópia) são solicitações educadas que os visualizadores podem honrar; qualquer biblioteca (incluindo pypdf) pode lê-los e removê-los. Apenas a senha do usuário realmente protege o conteúdo via criptografia. Nunca apresente flags de permissão como segurança.
- Extração de tabelas é heurística: o pdfplumber detecta tabelas a partir de linhas de régua/alinhamento de palavras; tabelas sem bordas ou com células mescladas podem precisar de ajustes em
table_settingsou limpeza manual. - Indexação de páginas: os CLIs auxiliares usam páginas base 1; as APIs do pypdf são base 0. Os scripts convertem — não faça dupla conversão.
- Extração de texto de carimbo girado: o agrupamento de linhas do pdfplumber embaralha glifos girados (um "RASCUNHO" a 45° é extraído como letras soltas); verifique carimbos girados com
extract_text()do pypdf ou uma imagem renderizada. - Grupos de opção: o reportlab precisa de ≥2 widgets
radio()por grupo, os preenchimentos precisam do valor de exportação com barra ("/red"), e a fidelidade de achatamento é pior para opções — vejareferences/forms.md. - Escopo de metadados:
pdf_meta.pyescreve apenas o dicionário DocInfo clássico; metadados XMP incorporados (se houver) permanecem intocados e podem mostrar valores diferentes em alguns visualizadores. - PDF/A está fora do escopo: pypdf/reportlab não podem produzir ou validar PDF/A conforme. Se a conformidade de arquivamento for necessária, execute o Ghostscript via a ferramenta
terminal(ex.:gs -dPDFA=2 -dPDFACompatibilityPolicy=1 -sColorConversionStrategy=UseDeviceIndependentColor -sDEVICE=pdfwrite -o out.pdf in.pdfcom um perfil ICC adequado) e valide com veraPDF — ambas são instalações externas, e o resultado ainda precisa de validação, não de suposição. - A rotação deve ser múltipla de 90; entradas criptografadas devem ser descriptografadas antes de qualquer outra operação.
Verificação
- Após criar/mesclar/dividir:
pdf_read.py out.pdf --meta— confirmepage_counterotationpor página quando você girou. - Após extrair: verifique se o JSON não está vazio e faça uma verificação pontual de uma string ou célula conhecida.
- Ciclo de design de formulário:
pdf_form_layout.py spec.jsondeve sair com código 0; depois--render-overlay boxes.png --pdf form.pdfe revise o PNG comvision_analyze(vermelho = caixas de entrada com nomes de campo, azul = caixas de rótulo) perguntando sobre sobreposições, desalinhamento e rótulos separados de seus campos. Itere especificação → verificação → sobreposição até ficar limpo. - Após construir um formulário:
pdf_read.py form.pdf --fieldslista todos os campos da especificação com o tipo e opções corretos. - Após preencher formulário:
pdf_read.py filled.pdf --fieldse compare os valores (correspondência exata, incluindo não ASCII). - Após carimbar: reextraia o texto (pypdf para carimbos girados) ou renderize a página com
pdf_page_image.pye inspecione comvision_analyze. - Após edições de metadados/anexos:
pdf_read.py --meta/pdf_meta.py --list-attachmentse reextraia um anexo para comparar byte a byte. - Após criptografar:
--metamostra"encrypted": truee abrir sem senha falha; após descriptografar, a extração de texto corresponde ao original. - Para qualquer coisa visual (marcas d'água, formulários achatados), renderize e inspecione com
vision_analyze.