[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-anthropics-skills-skills-pdf":3},{"error":4,"detail":5,"metadata":73,"markdownContent":75,"rawMarkdown":70},false,{"repo_full_name":6,"owner":7,"repo_name":8,"repo_forks":9,"skill_path":10,"repo_stars":11,"name":12,"category_id":13,"description":14,"file_tree":15,"skill_md_content":70,"skill_id":71,"skill_key":72},"anthropics/skills","anthropics","skills",10483,"skills/pdf",97092,"pdf",1,"Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill.",[16,21,25,29,33],{"name":17,"path":18,"size":19,"type":20},"LICENSE.txt","skills/pdf/LICENSE.txt",1467,"file",{"name":22,"path":23,"size":24,"type":20},"SKILL.md","skills/pdf/SKILL.md",8072,{"name":26,"path":27,"size":28,"type":20},"forms.md","skills/pdf/forms.md",11854,{"name":30,"path":31,"size":32,"type":20},"reference.md","skills/pdf/reference.md",16692,{"name":34,"path":35,"type":36,"children":37},"scripts","skills/pdf/scripts","folder",[38,42,46,50,54,58,62,66],{"name":39,"path":40,"size":41,"type":20},"check_bounding_boxes.py","skills/pdf/scripts/check_bounding_boxes.py",2774,{"name":43,"path":44,"size":45,"type":20},"check_fillable_fields.py","skills/pdf/scripts/check_fillable_fields.py",268,{"name":47,"path":48,"size":49,"type":20},"convert_pdf_to_images.py","skills/pdf/scripts/convert_pdf_to_images.py",1008,{"name":51,"path":52,"size":53,"type":20},"create_validation_image.py","skills/pdf/scripts/create_validation_image.py",1258,{"name":55,"path":56,"size":57,"type":20},"extract_form_field_info.py","skills/pdf/scripts/extract_form_field_info.py",4300,{"name":59,"path":60,"size":61,"type":20},"extract_form_structure.py","skills/pdf/scripts/extract_form_structure.py",3945,{"name":63,"path":64,"size":65,"type":20},"fill_fillable_fields.py","skills/pdf/scripts/fill_fillable_fields.py",3819,{"name":67,"path":68,"size":69,"type":20},"fill_pdf_form_with_annotations.py","skills/pdf/scripts/fill_pdf_form_with_annotations.py",3235,"---\nname: pdf\ndescription: Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill.\nlicense: Proprietary. LICENSE.txt has complete terms\n---\n\n# PDF Processing Guide\n\n## Overview\n\nThis guide covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see REFERENCE.md. If you need to fill out a PDF form, read FORMS.md and follow its instructions.\n\n## Quick Start\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Read a PDF\nreader = PdfReader(\"document.pdf\")\nprint(f\"Pages: {len(reader.pages)}\")\n\n# Extract text\ntext = \"\"\nfor page in reader.pages:\n    text += page.extract_text()\n```\n\n## Python Libraries\n\n### pypdf - Basic Operations\n\n#### Merge PDFs\n```python\nfrom pypdf import PdfWriter, PdfReader\n\nwriter = PdfWriter()\nfor pdf_file in [\"doc1.pdf\", \"doc2.pdf\", \"doc3.pdf\"]:\n    reader = PdfReader(pdf_file)\n    for page in reader.pages:\n        writer.add_page(page)\n\nwith open(\"merged.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n#### Split PDF\n```python\nreader = PdfReader(\"input.pdf\")\nfor i, page in enumerate(reader.pages):\n    writer = PdfWriter()\n    writer.add_page(page)\n    with open(f\"page_{i+1}.pdf\", \"wb\") as output:\n        writer.write(output)\n```\n\n#### Extract Metadata\n```python\nreader = PdfReader(\"document.pdf\")\nmeta = reader.metadata\nprint(f\"Title: {meta.title}\")\nprint(f\"Author: {meta.author}\")\nprint(f\"Subject: {meta.subject}\")\nprint(f\"Creator: {meta.creator}\")\n```\n\n#### Rotate Pages\n```python\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\npage = reader.pages[0]\npage.rotate(90)  # Rotate 90 degrees clockwise\nwriter.add_page(page)\n\nwith open(\"rotated.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### pdfplumber - Text and Table Extraction\n\n#### Extract Text with Layout\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for page in pdf.pages:\n        text = page.extract_text()\n        print(text)\n```\n\n#### Extract Tables\n```python\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for i, page in enumerate(pdf.pages):\n        tables = page.extract_tables()\n        for j, table in enumerate(tables):\n            print(f\"Table {j+1} on page {i+1}:\")\n            for row in table:\n                print(row)\n```\n\n#### Advanced Table Extraction\n```python\nimport pandas as pd\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    all_tables = []\n    for page in pdf.pages:\n        tables = page.extract_tables()\n        for table in tables:\n            if table:  # Check if table is not empty\n                df = pd.DataFrame(table[1:], columns=table[0])\n                all_tables.append(df)\n\n# Combine all tables\nif all_tables:\n    combined_df = pd.concat(all_tables, ignore_index=True)\n    combined_df.to_excel(\"extracted_tables.xlsx\", index=False)\n```\n\n### reportlab - Create PDFs\n\n#### Basic PDF Creation\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.pdfgen import canvas\n\nc = canvas.Canvas(\"hello.pdf\", pagesize=letter)\nwidth, height = letter\n\n# Add text\nc.drawString(100, height - 100, \"Hello World!\")\nc.drawString(100, height - 120, \"This is a PDF created with reportlab\")\n\n# Add a line\nc.line(100, height - 140, 400, height - 140)\n\n# Save\nc.save()\n```\n\n#### Create PDF with Multiple Pages\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak\nfrom reportlab.lib.styles import getSampleStyleSheet\n\ndoc = SimpleDocTemplate(\"report.pdf\", pagesize=letter)\nstyles = getSampleStyleSheet()\nstory = []\n\n# Add content\ntitle = Paragraph(\"Report Title\", styles['Title'])\nstory.append(title)\nstory.append(Spacer(1, 12))\n\nbody = Paragraph(\"This is the body of the report. \" * 20, styles['Normal'])\nstory.append(body)\nstory.append(PageBreak())\n\n# Page 2\nstory.append(Paragraph(\"Page 2\", styles['Heading1']))\nstory.append(Paragraph(\"Content for page 2\", styles['Normal']))\n\n# Build PDF\ndoc.build(story)\n```\n\n#### Subscripts and Superscripts\n\n**IMPORTANT**: Never use Unicode subscript/superscript characters (₀₁₂₃₄₅₆₇₈₉, ⁰¹²³⁴⁵⁶⁷⁸⁹) in ReportLab PDFs. The built-in fonts do not include these glyphs, causing them to render as solid black boxes.\n\nInstead, use ReportLab's XML markup tags in Paragraph objects:\n```python\nfrom reportlab.platypus import Paragraph\nfrom reportlab.lib.styles import getSampleStyleSheet\n\nstyles = getSampleStyleSheet()\n\n# Subscripts: use \u003Csub> tag\nchemical = Paragraph(\"H\u003Csub>2\u003C/sub>O\", styles['Normal'])\n\n# Superscripts: use \u003Csuper> tag\nsquared = Paragraph(\"x\u003Csuper>2\u003C/super> + y\u003Csuper>2\u003C/super>\", styles['Normal'])\n```\n\nFor canvas-drawn text (not Paragraph objects), manually adjust font the size and position rather than using Unicode subscripts/superscripts.\n\n## Command-Line Tools\n\n### pdftotext (poppler-utils)\n```bash\n# Extract text\npdftotext input.pdf output.txt\n\n# Extract text preserving layout\npdftotext -layout input.pdf output.txt\n\n# Extract specific pages\npdftotext -f 1 -l 5 input.pdf output.txt  # Pages 1-5\n```\n\n### qpdf\n```bash\n# Merge PDFs\nqpdf --empty --pages file1.pdf file2.pdf -- merged.pdf\n\n# Split pages\nqpdf input.pdf --pages . 1-5 -- pages1-5.pdf\nqpdf input.pdf --pages . 6-10 -- pages6-10.pdf\n\n# Rotate pages\nqpdf input.pdf output.pdf --rotate=+90:1  # Rotate page 1 by 90 degrees\n\n# Remove password\nqpdf --password=mypassword --decrypt encrypted.pdf decrypted.pdf\n```\n\n### pdftk (if available)\n```bash\n# Merge\npdftk file1.pdf file2.pdf cat output merged.pdf\n\n# Split\npdftk input.pdf burst\n\n# Rotate\npdftk input.pdf rotate 1east output rotated.pdf\n```\n\n## Common Tasks\n\n### Extract Text from Scanned PDFs\n```python\n# Requires: pip install pytesseract pdf2image\nimport pytesseract\nfrom pdf2image import convert_from_path\n\n# Convert PDF to images\nimages = convert_from_path('scanned.pdf')\n\n# OCR each page\ntext = \"\"\nfor i, image in enumerate(images):\n    text += f\"Page {i+1}:\\n\"\n    text += pytesseract.image_to_string(image)\n    text += \"\\n\\n\"\n\nprint(text)\n```\n\n### Add Watermark\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Create watermark (or load existing)\nwatermark = PdfReader(\"watermark.pdf\").pages[0]\n\n# Apply to all pages\nreader = PdfReader(\"document.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    page.merge_page(watermark)\n    writer.add_page(page)\n\nwith open(\"watermarked.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### Extract Images\n```bash\n# Using pdfimages (poppler-utils)\npdfimages -j input.pdf output_prefix\n\n# This extracts all images as output_prefix-000.jpg, output_prefix-001.jpg, etc.\n```\n\n### Password Protection\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    writer.add_page(page)\n\n# Add password\nwriter.encrypt(\"userpassword\", \"ownerpassword\")\n\nwith open(\"encrypted.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n## Quick Reference\n\n| Task | Best Tool | Command/Code |\n|------|-----------|--------------|\n| Merge PDFs | pypdf | `writer.add_page(page)` |\n| Split PDFs | pypdf | One page per file |\n| Extract text | pdfplumber | `page.extract_text()` |\n| Extract tables | pdfplumber | `page.extract_tables()` |\n| Create PDFs | reportlab | Canvas or Platypus |\n| Command line merge | qpdf | `qpdf --empty --pages ...` |\n| OCR scanned PDFs | pytesseract | Convert to image first |\n| Fill PDF forms | pdf-lib or pypdf (see FORMS.md) | See FORMS.md |\n\n## Next Steps\n\n- For advanced pypdfium2 usage, see REFERENCE.md\n- For JavaScript libraries (pdf-lib), see REFERENCE.md\n- If you need to fill out a PDF form, follow the instructions in FORMS.md\n- For troubleshooting guides, see REFERENCE.md\n","88438a58-311e-523e-af2d-b8c1a226a06e","anthropics-skills-skills-pdf",{"name":12,"description":14,"license":74},"Proprietary. LICENSE.txt has complete terms","\u003Ch1>PDF Processing Guide\u003C/h1>\n\u003Ch2>Overview\u003C/h2>\n\u003Cp>This guide covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see REFERENCE.md. If you need to fill out a PDF form, read FORMS.md and follow its instructions.\u003C/p>\n\u003Ch2>Quick Start\u003C/h2>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">from\u003C/span> pypdf \u003Cspan class=\"hljs-keyword\">import\u003C/span> PdfReader, PdfWriter\n\n\u003Cspan class=\"hljs-comment\"># Read a PDF\u003C/span>\nreader = PdfReader(\u003Cspan class=\"hljs-string\">&quot;document.pdf&quot;\u003C/span>)\n\u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Pages: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(reader.pages)}\u003C/span>&quot;\u003C/span>)\n\n\u003Cspan class=\"hljs-comment\"># Extract text\u003C/span>\ntext = \u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>\n\u003Cspan class=\"hljs-keyword\">for\u003C/span> page \u003Cspan class=\"hljs-keyword\">in\u003C/span> reader.pages:\n    text += page.extract_text()\u003C/code>\u003C/pre>\u003C/div>\u003Ch2>Python Libraries\u003C/h2>\n\u003Ch3>pypdf - Basic Operations\u003C/h3>\n\u003Ch4>Merge PDFs\u003C/h4>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">from\u003C/span> pypdf \u003Cspan class=\"hljs-keyword\">import\u003C/span> PdfWriter, PdfReader\n\nwriter = PdfWriter()\n\u003Cspan class=\"hljs-keyword\">for\u003C/span> pdf_file \u003Cspan class=\"hljs-keyword\">in\u003C/span> [\u003Cspan class=\"hljs-string\">&quot;doc1.pdf&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;doc2.pdf&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;doc3.pdf&quot;\u003C/span>]:\n    reader = PdfReader(pdf_file)\n    \u003Cspan class=\"hljs-keyword\">for\u003C/span> page \u003Cspan class=\"hljs-keyword\">in\u003C/span> reader.pages:\n        writer.add_page(page)\n\n\u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;merged.pdf&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;wb&quot;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> output:\n    writer.write(output)\u003C/code>\u003C/pre>\u003C/div>\u003Ch4>Split PDF\u003C/h4>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">reader = PdfReader(\u003Cspan class=\"hljs-string\">&quot;input.pdf&quot;\u003C/span>)\n\u003Cspan class=\"hljs-keyword\">for\u003C/span> i, page \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(reader.pages):\n    writer = PdfWriter()\n    writer.add_page(page)\n    \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;page_\u003Cspan class=\"hljs-subst\">{i+\u003Cspan class=\"hljs-number\">1\u003C/span>}\u003C/span>.pdf&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;wb&quot;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> output:\n        writer.write(output)\u003C/code>\u003C/pre>\u003C/div>\u003Ch4>Extract Metadata\u003C/h4>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">reader = PdfReader(\u003Cspan class=\"hljs-string\">&quot;document.pdf&quot;\u003C/span>)\nmeta = reader.metadata\n\u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Title: \u003Cspan class=\"hljs-subst\">{meta.title}\u003C/span>&quot;\u003C/span>)\n\u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Author: \u003Cspan class=\"hljs-subst\">{meta.author}\u003C/span>&quot;\u003C/span>)\n\u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Subject: \u003Cspan class=\"hljs-subst\">{meta.subject}\u003C/span>&quot;\u003C/span>)\n\u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Creator: \u003Cspan class=\"hljs-subst\">{meta.creator}\u003C/span>&quot;\u003C/span>)\u003C/code>\u003C/pre>\u003C/div>\u003Ch4>Rotate Pages\u003C/h4>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">reader = PdfReader(\u003Cspan class=\"hljs-string\">&quot;input.pdf&quot;\u003C/span>)\nwriter = PdfWriter()\n\npage = reader.pages[\u003Cspan class=\"hljs-number\">0\u003C/span>]\npage.rotate(\u003Cspan class=\"hljs-number\">90\u003C/span>)  \u003Cspan class=\"hljs-comment\"># Rotate 90 degrees clockwise\u003C/span>\nwriter.add_page(page)\n\n\u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;rotated.pdf&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;wb&quot;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> output:\n    writer.write(output)\u003C/code>\u003C/pre>\u003C/div>\u003Ch3>pdfplumber - Text and Table Extraction\u003C/h3>\n\u003Ch4>Extract Text with Layout\u003C/h4>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">import\u003C/span> pdfplumber\n\n\u003Cspan class=\"hljs-keyword\">with\u003C/span> pdfplumber.\u003Cspan class=\"hljs-built_in\">open\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;document.pdf&quot;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> pdf:\n    \u003Cspan class=\"hljs-keyword\">for\u003C/span> page \u003Cspan class=\"hljs-keyword\">in\u003C/span> pdf.pages:\n        text = page.extract_text()\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(text)\u003C/code>\u003C/pre>\u003C/div>\u003Ch4>Extract Tables\u003C/h4>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">with\u003C/span> pdfplumber.\u003Cspan class=\"hljs-built_in\">open\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;document.pdf&quot;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> pdf:\n    \u003Cspan class=\"hljs-keyword\">for\u003C/span> i, page \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(pdf.pages):\n        tables = page.extract_tables()\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> j, table \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(tables):\n            \u003Cspan class=\"hljs-built_in\">print\u003C/span>(\u003Cspan class=\"hljs-string\">f&quot;Table \u003Cspan class=\"hljs-subst\">{j+\u003Cspan class=\"hljs-number\">1\u003C/span>}\u003C/span> on page \u003Cspan class=\"hljs-subst\">{i+\u003Cspan class=\"hljs-number\">1\u003C/span>}\u003C/span>:&quot;\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> row \u003Cspan class=\"hljs-keyword\">in\u003C/span> table:\n                \u003Cspan class=\"hljs-built_in\">print\u003C/span>(row)\u003C/code>\u003C/pre>\u003C/div>\u003Ch4>Advanced Table Extraction\u003C/h4>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">import\u003C/span> pandas \u003Cspan class=\"hljs-keyword\">as\u003C/span> pd\n\n\u003Cspan class=\"hljs-keyword\">with\u003C/span> pdfplumber.\u003Cspan class=\"hljs-built_in\">open\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;document.pdf&quot;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> pdf:\n    all_tables = []\n    \u003Cspan class=\"hljs-keyword\">for\u003C/span> page \u003Cspan class=\"hljs-keyword\">in\u003C/span> pdf.pages:\n        tables = page.extract_tables()\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> table \u003Cspan class=\"hljs-keyword\">in\u003C/span> tables:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> table:  \u003Cspan class=\"hljs-comment\"># Check if table is not empty\u003C/span>\n                df = pd.DataFrame(table[\u003Cspan class=\"hljs-number\">1\u003C/span>:], columns=table[\u003Cspan class=\"hljs-number\">0\u003C/span>])\n                all_tables.append(df)\n\n\u003Cspan class=\"hljs-comment\"># Combine all tables\u003C/span>\n\u003Cspan class=\"hljs-keyword\">if\u003C/span> all_tables:\n    combined_df = pd.concat(all_tables, ignore_index=\u003Cspan class=\"hljs-literal\">True\u003C/span>)\n    combined_df.to_excel(\u003Cspan class=\"hljs-string\">&quot;extracted_tables.xlsx&quot;\u003C/span>, index=\u003Cspan class=\"hljs-literal\">False\u003C/span>)\u003C/code>\u003C/pre>\u003C/div>\u003Ch3>reportlab - Create PDFs\u003C/h3>\n\u003Ch4>Basic PDF Creation\u003C/h4>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">from\u003C/span> reportlab.lib.pagesizes \u003Cspan class=\"hljs-keyword\">import\u003C/span> letter\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> reportlab.pdfgen \u003Cspan class=\"hljs-keyword\">import\u003C/span> canvas\n\nc = canvas.Canvas(\u003Cspan class=\"hljs-string\">&quot;hello.pdf&quot;\u003C/span>, pagesize=letter)\nwidth, height = letter\n\n\u003Cspan class=\"hljs-comment\"># Add text\u003C/span>\nc.drawString(\u003Cspan class=\"hljs-number\">100\u003C/span>, height - \u003Cspan class=\"hljs-number\">100\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;Hello World!&quot;\u003C/span>)\nc.drawString(\u003Cspan class=\"hljs-number\">100\u003C/span>, height - \u003Cspan class=\"hljs-number\">120\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;This is a PDF created with reportlab&quot;\u003C/span>)\n\n\u003Cspan class=\"hljs-comment\"># Add a line\u003C/span>\nc.line(\u003Cspan class=\"hljs-number\">100\u003C/span>, height - \u003Cspan class=\"hljs-number\">140\u003C/span>, \u003Cspan class=\"hljs-number\">400\u003C/span>, height - \u003Cspan class=\"hljs-number\">140\u003C/span>)\n\n\u003Cspan class=\"hljs-comment\"># Save\u003C/span>\nc.save()\u003C/code>\u003C/pre>\u003C/div>\u003Ch4>Create PDF with Multiple Pages\u003C/h4>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">from\u003C/span> reportlab.lib.pagesizes \u003Cspan class=\"hljs-keyword\">import\u003C/span> letter\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> reportlab.platypus \u003Cspan class=\"hljs-keyword\">import\u003C/span> SimpleDocTemplate, Paragraph, Spacer, PageBreak\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> reportlab.lib.styles \u003Cspan class=\"hljs-keyword\">import\u003C/span> getSampleStyleSheet\n\ndoc = SimpleDocTemplate(\u003Cspan class=\"hljs-string\">&quot;report.pdf&quot;\u003C/span>, pagesize=letter)\nstyles = getSampleStyleSheet()\nstory = []\n\n\u003Cspan class=\"hljs-comment\"># Add content\u003C/span>\ntitle = Paragraph(\u003Cspan class=\"hljs-string\">&quot;Report Title&quot;\u003C/span>, styles[\u003Cspan class=\"hljs-string\">&#x27;Title&#x27;\u003C/span>])\nstory.append(title)\nstory.append(Spacer(\u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-number\">12\u003C/span>))\n\nbody = Paragraph(\u003Cspan class=\"hljs-string\">&quot;This is the body of the report. &quot;\u003C/span> * \u003Cspan class=\"hljs-number\">20\u003C/span>, styles[\u003Cspan class=\"hljs-string\">&#x27;Normal&#x27;\u003C/span>])\nstory.append(body)\nstory.append(PageBreak())\n\n\u003Cspan class=\"hljs-comment\"># Page 2\u003C/span>\nstory.append(Paragraph(\u003Cspan class=\"hljs-string\">&quot;Page 2&quot;\u003C/span>, styles[\u003Cspan class=\"hljs-string\">&#x27;Heading1&#x27;\u003C/span>]))\nstory.append(Paragraph(\u003Cspan class=\"hljs-string\">&quot;Content for page 2&quot;\u003C/span>, styles[\u003Cspan class=\"hljs-string\">&#x27;Normal&#x27;\u003C/span>]))\n\n\u003Cspan class=\"hljs-comment\"># Build PDF\u003C/span>\ndoc.build(story)\u003C/code>\u003C/pre>\u003C/div>\u003Ch4>Subscripts and Superscripts\u003C/h4>\n\u003Cp>\u003Cstrong>IMPORTANT\u003C/strong>: Never use Unicode subscript/superscript characters (₀₁₂₃₄₅₆₇₈₉, ⁰¹²³⁴⁵⁶⁷⁸⁹) in ReportLab PDFs. The built-in fonts do not include these glyphs, causing them to render as solid black boxes.\u003C/p>\n\u003Cp>Instead, use ReportLab&#39;s XML markup tags in Paragraph objects:\u003C/p>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">from\u003C/span> reportlab.platypus \u003Cspan class=\"hljs-keyword\">import\u003C/span> Paragraph\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> reportlab.lib.styles \u003Cspan class=\"hljs-keyword\">import\u003C/span> getSampleStyleSheet\n\nstyles = getSampleStyleSheet()\n\n\u003Cspan class=\"hljs-comment\"># Subscripts: use &lt;sub&gt; tag\u003C/span>\nchemical = Paragraph(\u003Cspan class=\"hljs-string\">&quot;H&lt;sub&gt;2&lt;/sub&gt;O&quot;\u003C/span>, styles[\u003Cspan class=\"hljs-string\">&#x27;Normal&#x27;\u003C/span>])\n\n\u003Cspan class=\"hljs-comment\"># Superscripts: use &lt;super&gt; tag\u003C/span>\nsquared = Paragraph(\u003Cspan class=\"hljs-string\">&quot;x&lt;super&gt;2&lt;/super&gt; + y&lt;super&gt;2&lt;/super&gt;&quot;\u003C/span>, styles[\u003Cspan class=\"hljs-string\">&#x27;Normal&#x27;\u003C/span>])\u003C/code>\u003C/pre>\u003C/div>\u003Cp>For canvas-drawn text (not Paragraph objects), manually adjust font the size and position rather than using Unicode subscripts/superscripts.\u003C/p>\n\u003Ch2>Command-Line Tools\u003C/h2>\n\u003Ch3>pdftotext (poppler-utils)\u003C/h3>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">bash\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Extract text\u003C/span>\npdftotext input.pdf output.txt\n\n\u003Cspan class=\"hljs-comment\"># Extract text preserving layout\u003C/span>\npdftotext -layout input.pdf output.txt\n\n\u003Cspan class=\"hljs-comment\"># Extract specific pages\u003C/span>\npdftotext -f 1 -l 5 input.pdf output.txt  \u003Cspan class=\"hljs-comment\"># Pages 1-5\u003C/span>\u003C/code>\u003C/pre>\u003C/div>\u003Ch3>qpdf\u003C/h3>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">bash\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Merge PDFs\u003C/span>\nqpdf --empty --pages file1.pdf file2.pdf -- merged.pdf\n\n\u003Cspan class=\"hljs-comment\"># Split pages\u003C/span>\nqpdf input.pdf --pages . 1-5 -- pages1-5.pdf\nqpdf input.pdf --pages . 6-10 -- pages6-10.pdf\n\n\u003Cspan class=\"hljs-comment\"># Rotate pages\u003C/span>\nqpdf input.pdf output.pdf --rotate=+90:1  \u003Cspan class=\"hljs-comment\"># Rotate page 1 by 90 degrees\u003C/span>\n\n\u003Cspan class=\"hljs-comment\"># Remove password\u003C/span>\nqpdf --password=mypassword --decrypt encrypted.pdf decrypted.pdf\u003C/code>\u003C/pre>\u003C/div>\u003Ch3>pdftk (if available)\u003C/h3>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">bash\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Merge\u003C/span>\npdftk file1.pdf file2.pdf \u003Cspan class=\"hljs-built_in\">cat\u003C/span> output merged.pdf\n\n\u003Cspan class=\"hljs-comment\"># Split\u003C/span>\npdftk input.pdf burst\n\n\u003Cspan class=\"hljs-comment\"># Rotate\u003C/span>\npdftk input.pdf rotate 1east output rotated.pdf\u003C/code>\u003C/pre>\u003C/div>\u003Ch2>Common Tasks\u003C/h2>\n\u003Ch3>Extract Text from Scanned PDFs\u003C/h3>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-comment\"># Requires: pip install pytesseract pdf2image\u003C/span>\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> pytesseract\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> pdf2image \u003Cspan class=\"hljs-keyword\">import\u003C/span> convert_from_path\n\n\u003Cspan class=\"hljs-comment\"># Convert PDF to images\u003C/span>\nimages = convert_from_path(\u003Cspan class=\"hljs-string\">&#x27;scanned.pdf&#x27;\u003C/span>)\n\n\u003Cspan class=\"hljs-comment\"># OCR each page\u003C/span>\ntext = \u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>\n\u003Cspan class=\"hljs-keyword\">for\u003C/span> i, image \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(images):\n    text += \u003Cspan class=\"hljs-string\">f&quot;Page \u003Cspan class=\"hljs-subst\">{i+\u003Cspan class=\"hljs-number\">1\u003C/span>}\u003C/span>:\\n&quot;\u003C/span>\n    text += pytesseract.image_to_string(image)\n    text += \u003Cspan class=\"hljs-string\">&quot;\\n\\n&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-built_in\">print\u003C/span>(text)\u003C/code>\u003C/pre>\u003C/div>\u003Ch3>Add Watermark\u003C/h3>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">from\u003C/span> pypdf \u003Cspan class=\"hljs-keyword\">import\u003C/span> PdfReader, PdfWriter\n\n\u003Cspan class=\"hljs-comment\"># Create watermark (or load existing)\u003C/span>\nwatermark = PdfReader(\u003Cspan class=\"hljs-string\">&quot;watermark.pdf&quot;\u003C/span>).pages[\u003Cspan class=\"hljs-number\">0\u003C/span>]\n\n\u003Cspan class=\"hljs-comment\"># Apply to all pages\u003C/span>\nreader = PdfReader(\u003Cspan class=\"hljs-string\">&quot;document.pdf&quot;\u003C/span>)\nwriter = PdfWriter()\n\n\u003Cspan class=\"hljs-keyword\">for\u003C/span> page \u003Cspan class=\"hljs-keyword\">in\u003C/span> reader.pages:\n    page.merge_page(watermark)\n    writer.add_page(page)\n\n\u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;watermarked.pdf&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;wb&quot;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> output:\n    writer.write(output)\u003C/code>\u003C/pre>\u003C/div>\u003Ch3>Extract Images\u003C/h3>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">bash\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Using pdfimages (poppler-utils)\u003C/span>\npdfimages -j input.pdf output_prefix\n\n\u003Cspan class=\"hljs-comment\"># This extracts all images as output_prefix-000.jpg, output_prefix-001.jpg, etc.\u003C/span>\u003C/code>\u003C/pre>\u003C/div>\u003Ch3>Password Protection\u003C/h3>\n\u003Cdiv class=\"md-code-block\">\u003Cdiv class=\"md-code-lang\">python\u003C/div>\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-keyword\">from\u003C/span> pypdf \u003Cspan class=\"hljs-keyword\">import\u003C/span> PdfReader, PdfWriter\n\nreader = PdfReader(\u003Cspan class=\"hljs-string\">&quot;input.pdf&quot;\u003C/span>)\nwriter = PdfWriter()\n\n\u003Cspan class=\"hljs-keyword\">for\u003C/span> page \u003Cspan class=\"hljs-keyword\">in\u003C/span> reader.pages:\n    writer.add_page(page)\n\n\u003Cspan class=\"hljs-comment\"># Add password\u003C/span>\nwriter.encrypt(\u003Cspan class=\"hljs-string\">&quot;userpassword&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;ownerpassword&quot;\u003C/span>)\n\n\u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(\u003Cspan class=\"hljs-string\">&quot;encrypted.pdf&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;wb&quot;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> output:\n    writer.write(output)\u003C/code>\u003C/pre>\u003C/div>\u003Ch2>Quick Reference\u003C/h2>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Task\u003C/th>\n\u003Cth>Best Tool\u003C/th>\n\u003Cth>Command/Code\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>Merge PDFs\u003C/td>\n\u003Ctd>pypdf\u003C/td>\n\u003Ctd>\u003Ccode>writer.add_page(page)\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Split PDFs\u003C/td>\n\u003Ctd>pypdf\u003C/td>\n\u003Ctd>One page per file\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Extract text\u003C/td>\n\u003Ctd>pdfplumber\u003C/td>\n\u003Ctd>\u003Ccode>page.extract_text()\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Extract tables\u003C/td>\n\u003Ctd>pdfplumber\u003C/td>\n\u003Ctd>\u003Ccode>page.extract_tables()\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Create PDFs\u003C/td>\n\u003Ctd>reportlab\u003C/td>\n\u003Ctd>Canvas or Platypus\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Command line merge\u003C/td>\n\u003Ctd>qpdf\u003C/td>\n\u003Ctd>\u003Ccode>qpdf --empty --pages ...\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>OCR scanned PDFs\u003C/td>\n\u003Ctd>pytesseract\u003C/td>\n\u003Ctd>Convert to image first\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Fill PDF forms\u003C/td>\n\u003Ctd>pdf-lib or pypdf (see FORMS.md)\u003C/td>\n\u003Ctd>See FORMS.md\u003C/td>\n\u003C/tr>\n\u003C/tbody>\u003C/table>\n\u003Ch2>Next Steps\u003C/h2>\n\u003Cul>\n\u003Cli>For advanced pypdfium2 usage, see REFERENCE.md\u003C/li>\n\u003Cli>For JavaScript libraries (pdf-lib), see REFERENCE.md\u003C/li>\n\u003Cli>If you need to fill out a PDF form, follow the instructions in FORMS.md\u003C/li>\n\u003Cli>For troubleshooting guides, see REFERENCE.md\u003C/li>\n\u003C/ul>\n"]