pypdf-5-text-extraction-and-metadata

Sub-skill of pypdf: 5. Text Extraction and Metadata.

5 stars

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

$curl -o ~/.claude/skills/5-text-extraction-and-metadata/SKILL.md --create-dirs "https://raw.githubusercontent.com/vamseeachanta/workspace-hub/main/.agents/skills/_archive/data/office/pypdf/5-text-extraction-and-metadata/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/5-text-extraction-and-metadata/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How pypdf-5-text-extraction-and-metadata Compares

Feature / Agentpypdf-5-text-extraction-and-metadataStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/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

5
from vamseeachanta/workspace-hub

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

5
from vamseeachanta/workspace-hub

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

5
from vamseeachanta/workspace-hub

Extract and separate portable baseline config from machine-specific overrides in multi-environment projects

metadata-only-wiki-sweep-workflow

5
from vamseeachanta/workspace-hub

Disciplined inventory process for cataloging documents by filename/path without content claims, using parent-centric grouping to prevent stub proliferation

metadata-only-inventory-sweep

5
from vamseeachanta/workspace-hub

Execute constrained file inventory sweeps with metadata-only stubs and validation, useful for staged documentation work on large file sets

wiki-context

5
from vamseeachanta/workspace-hub

Auto-query llm-wiki domains for relevant context before executing domain tasks

doc-extraction-naval-architecture

5
from vamseeachanta/workspace-hub

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

5
from vamseeachanta/workspace-hub

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

5
from vamseeachanta/workspace-hub

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

5
from vamseeachanta/workspace-hub

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

5
from vamseeachanta/workspace-hub

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

5
from vamseeachanta/workspace-hub

Sub-skill of pdf-text-extractor: Readability Classification.