Skill GLOBAL es
PDF Processing
Crea, lee, modifica y procesa archivos PDF: extraer texto y tablas, unir, dividir, rotar, añadir marcas de agua, proteger con contraseña, OCR de documentos escaneados y generación de PDFs desde cero.
Contenido completo
---
name: pdf
description: Use this skill for any PDF task — reading, extracting text/tables/images, merging, splitting, rotating, watermarking, encrypting, OCR on scanned PDFs, creating PDFs from scratch, or filling PDF forms. Trigger on any mention of .pdf files or requests to produce one.
---
# PDF Processing
## Python Libraries
### pypdf — Core Operations
```python
from pypdf import PdfReader, PdfWriter
# Read
reader = PdfReader("doc.pdf")
print(f"Pages: {len(reader.pages)}")
# Extract text
text = "\n\n".join(p.extract_text() for p in reader.pages)
# Merge
writer = PdfWriter()
for f in ["a.pdf", "b.pdf"]:
for p in PdfReader(f).pages:
writer.add_page(p)
with open("merged.pdf", "wb") as out:
writer.write(out)
# Split (one PDF per page)
for i, page in enumerate(reader.pages):
w = PdfWriter()
w.add_page(page)
with open(f"p{i}.pdf", "wb") as out:
w.write(out)
# Rotate (90° clockwise on page 1)
reader.pages[0].rotate(90)
# Encrypt
writer.encrypt("user", "owner")
# Watermark
wm = PdfReader("wm.pdf").pages[0]
for page in reader.pages:
page.merge_page(wm)
writer.add_page(page)
# Metadata
meta = reader.metadata
print(meta.title, meta.author, meta.creator)
```
### pdfplumber — Text & Table Extraction
```python
import pdfplumber
with pdfplumber.open("doc.pdf") as pdf:
for page in pdf.pages:
text = page.extract_text()
tables = page.extract_tables()
for t in tables:
for row in t:
print(row)
# To pandas DataFrame
import pandas as pd
tables = []
with pdfplumber.open("doc.pdf") as pdf:
for page in pdf.pages:
for t in page.extract_tables():
if t:
df = pd.DataFrame(t[1:], columns=t[0])
tables.append(df)
if tables:
pd.concat(tables, ignore_index=True).to_excel("tables.xlsx", index=False)
```
### reportlab — PDF Creation
```python
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
from reportlab.lib.styles import getSampleStyleSheet
doc = SimpleDocTemplate("report.pdf", pagesize=letter)
styles = getSampleStyleSheet()
story = [
Paragraph("Title", styles['Title']),
Spacer(1, 12),
Paragraph("Body text here.", styles['Normal']),
PageBreak(),
Paragraph("Page 2", styles['Heading1']),
]
doc.build(story)
# Subscripts/superscripts: use XML tags, NOT Unicode
p = Paragraph("H<sub>2</sub>O and x<super>2</super>", styles['Normal'])
```
## CLI Tools
```bash
# Extract text (poppler-utils)
pdftotext input.pdf output.txt
pdftotext -layout input.pdf output.txt # preserve layout
pdftotext -f 1 -l 5 input.pdf out.txt # pages 1-5
# Merge/split/rotate (qpdf)
qpdf --empty --pages a.pdf b.pdf -- merged.pdf
qpdf input.pdf --pages . 1-5 -- part1.pdf
qpdf input.pdf output.pdf --rotate=+90:1 # rotate page 1
# Extract images (poppler-utils)
pdfimages -j input.pdf out_prefix # out_prefix-000.jpg, ...
# Decrypt
qpdf --password=mypwd --decrypt in.pdf out.pdf
```
## OCR (Scanned PDFs)
```python
import pytesseract
from pdf2image import convert_from_path
images = convert_from_path('scanned.pdf')
for i, img in enumerate(images):
print(f"Page {i+1}:\n{pytesseract.image_to_string(img)}\n")
```
## Quick Reference
| Task | Best Tool | Key API |
|------|-----------|---------|
| Merge/split/rotate | pypdf | `writer.add_page(page)` |
| Extract text | pdfplumber | `page.extract_text()` |
| Extract tables | pdfplumber | `page.extract_tables()` → pandas |
| Create PDF | reportlab | `doc.build(story)` |
| CLI merge/split | qpdf | `qpdf --empty --pages` |
| OCR | pytesseract | `image_to_string(img)` |
| Watermark | pypdf | `page.merge_page(wm)` |
| Encrypt | pypdf | `writer.encrypt()` |
| Extract images | pdfimages | `pdfimages -j` |
## Pitfalls
- **Unicode sub/superscripts** in ReportLab render as black boxes — always use `<sub>` / `<super>` XML tags.
- **`data_only=True`** in openpyxl replaces formulas with values permanently — never use for PDF-related Excel intermediates.
- **Scanned PDFs** return no text from `extract_text()` — use OCR pipeline.
- **Table extraction** may produce None rows — filter with `if t:` before converting.