pypdf-5-text-extraction-and-metadata
Sub-skill of pypdf: 5. Text Extraction and Metadata.
Best use case
pypdf-5-text-extraction-and-metadata is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Sub-skill of pypdf: 5. Text Extraction and Metadata.
Teams using pypdf-5-text-extraction-and-metadata should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/5-text-extraction-and-metadata/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How pypdf-5-text-extraction-and-metadata Compares
| Feature / Agent | pypdf-5-text-extraction-and-metadata | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Sub-skill of pypdf: 5. Text Extraction and Metadata.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# 5. Text Extraction and Metadata
## 5. Text Extraction and Metadata
```python
"""
Extract text and manage PDF metadata.
"""
from pypdf import PdfReader, PdfWriter
from pathlib import Path
from typing import Dict, Optional, List
from datetime import datetime
def extract_text(
input_path: str,
pages: Optional[List[int]] = None,
preserve_layout: bool = False
) -> str:
"""Extract text from PDF.
Args:
input_path: Source PDF file
pages: List of page numbers to extract (0-indexed), None for all
preserve_layout: Try to preserve text layout
Returns:
Extracted text as string
"""
reader = PdfReader(input_path)
text_parts = []
target_pages = pages if pages else range(len(reader.pages))
for page_num in target_pages:
if 0 <= page_num < len(reader.pages):
page = reader.pages[page_num]
if preserve_layout:
page_text = page.extract_text(extraction_mode="layout")
else:
page_text = page.extract_text()
if page_text:
text_parts.append(f"--- Page {page_num + 1} ---\n{page_text}")
return "\n\n".join(text_parts)
def extract_text_to_file(
input_path: str,
output_path: str,
pages: Optional[List[int]] = None
) -> int:
"""Extract text from PDF and save to file."""
text = extract_text(input_path, pages)
with open(output_path, 'w', encoding='utf-8') as f:
f.write(text)
word_count = len(text.split())
print(f"Extracted {word_count} words to: {output_path}")
return word_count
def get_pdf_info(input_path: str) -> Dict:
"""Get PDF document information and metadata."""
reader = PdfReader(input_path)
info = {
'file_path': input_path,
'num_pages': len(reader.pages),
'is_encrypted': reader.is_encrypted,
'metadata': {}
}
# Get metadata
if reader.metadata:
metadata = reader.metadata
info['metadata'] = {
'title': metadata.get('/Title', ''),
'author': metadata.get('/Author', ''),
'subject': metadata.get('/Subject', ''),
'creator': metadata.get('/Creator', ''),
'producer': metadata.get('/Producer', ''),
'creation_date': str(metadata.get('/CreationDate', '')),
'modification_date': str(metadata.get('/ModDate', ''))
}
# Get page dimensions of first page
if reader.pages:
first_page = reader.pages[0]
info['page_width'] = float(first_page.mediabox.width)
info['page_height'] = float(first_page.mediabox.height)
info['page_size_inches'] = (
info['page_width'] / 72,
info['page_height'] / 72
)
return info
def set_pdf_metadata(
input_path: str,
output_path: str,
metadata: Dict[str, str]
) -> None:
"""Set PDF metadata.
Args:
input_path: Source PDF file
output_path: Destination file
metadata: Dictionary with keys: title, author, subject, keywords, creator
"""
reader = PdfReader(input_path)
writer = PdfWriter()
# Copy pages
for page in reader.pages:
writer.add_page(page)
# Set metadata
writer.add_metadata({
'/Title': metadata.get('title', ''),
'/Author': metadata.get('author', ''),
'/Subject': metadata.get('subject', ''),
'/Keywords': metadata.get('keywords', ''),
'/Creator': metadata.get('creator', 'pypdf'),
'/Producer': 'pypdf',
'/ModDate': datetime.now().strftime("D:%Y%m%d%H%M%S")
})
writer.write(output_path)
print(f"Metadata updated: {output_path}")
def search_pdf(
input_path: str,
search_term: str,
case_sensitive: bool = False
) -> List[Dict]:
"""Search for text in PDF and return page numbers and context."""
reader = PdfReader(input_path)
results = []
for i, page in enumerate(reader.pages):
text = page.extract_text()
if not text:
continue
search_text = text if case_sensitive else text.lower()
term = search_term if case_sensitive else search_term.lower()
if term in search_text:
# Find context around match
idx = search_text.find(term)
start = max(0, idx - 50)
end = min(len(text), idx + len(term) + 50)
context = text[start:end].replace('\n', ' ')
results.append({
'page': i + 1,
'context': f"...{context}..."
})
return results
# Example usage
# text = extract_text('document.pdf')
# info = get_pdf_info('document.pdf')
# set_pdf_metadata('document.pdf', 'with_metadata.pdf', {
# 'title': 'My Document',
# 'author': 'John Doe',
# 'subject': 'Report'
# })
# results = search_pdf('document.pdf', 'important')
```Related Skills
llm-wiki-source-extraction-coverage
Doc-type-aware extraction contract for llm-wiki source ingestion with measurable coverage and source-anchored traceability. Use when (1) ingesting a PDF, DOCX, XLSX, PPTX, HTML, or scanned-image source into a wiki `sources/` page, (2) computing the pre-extraction estimate (what fraction of the source we expect to recover) and post-extraction yield (what fraction we actually recovered), (3) anchoring wiki claims back to specific page / paragraph / cell / slide positions in the source so a reviewer can re-verify or revise against the actual document, (4) deciding whether OCR fallback or manual transcription is needed. Codifies workspace-hub's existing OCR fallback chain and python-docx / openpyxl / trafilatura patterns into a format-specific routing table. Companion to research/llm-wiki-page-shape-contract (Rule 7 input-layer pages) and research/llm-wiki — this skill is the defense against silent extraction failure.
context-compaction-handoff
Guardrails for resuming work after context compaction or transcript handoff blocks; prioritize the latest real user request over stale summarized tasks and verify before answering.
portable-baseline-pattern-extraction
Extract and separate portable baseline config from machine-specific overrides in multi-environment projects
metadata-only-wiki-sweep-workflow
Disciplined inventory process for cataloging documents by filename/path without content claims, using parent-centric grouping to prevent stub proliferation
metadata-only-inventory-sweep
Execute constrained file inventory sweeps with metadata-only stubs and validation, useful for staged documentation work on large file sets
wiki-context
Auto-query llm-wiki domains for relevant context before executing domain tasks
doc-extraction-naval-architecture
Layer 3 domain sub-skill for extracting naval architecture data from SNAME PNA, IMO stability codes, IACS structural rules, and classification society guidelines. Provides detection heuristics for stability constants, resistance equations, hull form coefficients, hydrostatic curves, IMO stability criteria, and structural scantling tables. type: reference
doc-extraction-drilling-riser
Layer 3 domain sub-skill for extracting drilling riser data from API RP 16Q, DNV-RP-C205, and riser analysis reports. Provides detection heuristics for VIV parameters, kill/choke line specs, and BOP stack configurations. type: reference
doc-extraction
Classify and extract structured content from engineering documents using a 3-layer taxonomy: generic content types, engineering patterns, and domain sub-skills. Use when ingesting standards, reports, or technical manuals into structured data for downstream analysis. type: reference
gmail-email-to-repo-extraction
Extract structured data from Gmail inbox emails, enrich with domain-specific classification, legal-scan against deny list, commit to appropriate repo, then optionally delete originals.
gmail-data-extraction
Extract structured data from Gmail emails using REST API (no pip dependencies). Covers inbox scanning, subject line regex extraction, email text parsing, thread-aware drafting, and legal-scan-before-commit workflow.
pdf-text-extractor-readability-classification
Sub-skill of pdf-text-extractor: Readability Classification.