PDF Extraction Skill Overview This skill enables precise extraction of text, tables, and metadata from PDF documents using pdfplumber - the go-to library for PDF data extraction. Unlike basic PDF readers, pdfplumber provides detailed character-level positioning, accurate table detection, and visual debugging. How to Use 1. Provide the PDF file you want to extract from 2. Specify what you need: text, tables, images, or metadata 3. I'll generate pdfplumber code and execute it Example prompts: - "Extract all tables from this financial report" - "Get text from pages 5-10 of this document" - "Find…

, '')\n try:\n return float(text)\n except ValueError:\n continue\n \n return None\n```\n\n### Multi-column Layout\n```python\ndef extract_columns(page, num_columns=2):\n \"\"\"Extract text from multi-column layout.\"\"\"\n width = page.width\n col_width = width / num_columns\n \n columns = []\n for i in range(num_columns):\n x0 = i * col_width\n x1 = (i + 1) * col_width\n \n cropped = page.crop((x0, 0, x1, page.height))\n columns.append(cropped.extract_text())\n \n return columns\n```\n\n## Examples\n\n### Example 1: Financial Report Table Extraction\n```python\nimport pdfplumber\nimport pandas as pd\n\ndef extract_financial_tables(pdf_path):\n \"\"\"Extract tables from financial report and save to Excel.\"\"\"\n \n with pdfplumber.open(pdf_path) as pdf:\n all_tables = []\n \n for page_num, page in enumerate(pdf.pages):\n # Debug: save table visualization\n im = page.to_image()\n im.debug_tablefinder()\n im.save(f'debug_page_{page_num+1}.png')\n \n # Extract tables\n tables = page.extract_tables({\n \"vertical_strategy\": \"lines\",\n \"horizontal_strategy\": \"lines\",\n \"snap_tolerance\": 5,\n })\n \n for table in tables:\n if table and len(table) > 1:\n # Clean data\n clean_table = []\n for row in table:\n clean_row = [cell.strip() if cell else '' for cell in row]\n clean_table.append(clean_row)\n \n df = pd.DataFrame(clean_table[1:], columns=clean_table[0])\n df['Source Page'] = page_num + 1\n all_tables.append(df)\n \n # Save to Excel with multiple sheets\n with pd.ExcelWriter('extracted_tables.xlsx') as writer:\n for i, df in enumerate(all_tables):\n df.to_excel(writer, sheet_name=f'Table_{i+1}', index=False)\n \n return all_tables\n\ntables = extract_financial_tables('annual_report.pdf')\nprint(f\"Extracted {len(tables)} tables\")\n```\n\n### Example 2: Invoice Data Extraction\n```python\nimport pdfplumber\nimport re\nfrom datetime import datetime\n\ndef extract_invoice_data(pdf_path):\n \"\"\"Extract structured data from invoice PDF.\"\"\"\n \n data = {\n 'invoice_number': None,\n 'date': None,\n 'total': None,\n 'line_items': []\n }\n \n with pdfplumber.open(pdf_path) as pdf:\n page = pdf.pages[0]\n text = page.extract_text()\n \n # Extract invoice number\n inv_match = re.search(r'Invoice\\s*#?\\s*:?\\s*(\\w+)', text, re.IGNORECASE)\n if inv_match:\n data['invoice_number'] = inv_match.group(1)\n \n # Extract date\n date_match = re.search(r'Date\\s*:?\\s*(\\d{1,2}[/-]\\d{1,2}[/-]\\d{2,4})', text)\n if date_match:\n data['date'] = date_match.group(1)\n \n # Extract total\n total_match = re.search(r'Total\\s*:?\\s*\\$?([\\d,]+\\.?\\d*)', text, re.IGNORECASE)\n if total_match:\n data['total'] = float(total_match.group(1).replace(',', ''))\n \n # Extract line items from table\n tables = page.extract_tables()\n for table in tables:\n if table and any('description' in str(row).lower() for row in table[:2]):\n # Found line items table\n for row in table[1:]: # Skip header\n if row and len(row) >= 3:\n data['line_items'].append({\n 'description': row[0],\n 'quantity': row[1] if len(row) > 1 else None,\n 'amount': row[-1]\n })\n \n return data\n\ninvoice = extract_invoice_data('invoice.pdf')\nprint(f\"Invoice #{invoice['invoice_number']}\")\nprint(f\"Total: ${invoice['total']}\")\n```\n\n### Example 3: Resume/CV Parser\n```python\nimport pdfplumber\n\ndef parse_resume(pdf_path):\n \"\"\"Extract structured sections from resume.\"\"\"\n \n with pdfplumber.open(pdf_path) as pdf:\n full_text = ''\n for page in pdf.pages:\n full_text += (page.extract_text() or '') + '\\n'\n \n # Common resume sections\n sections = {\n 'contact': '',\n 'summary': '',\n 'experience': '',\n 'education': '',\n 'skills': ''\n }\n \n # Split by common headers\n import re\n section_patterns = {\n 'summary': r'(summary|objective|profile)',\n 'experience': r'(experience|employment|work history)',\n 'education': r'(education|academic)',\n 'skills': r'(skills|competencies|technical)'\n }\n \n lines = full_text.split('\\n')\n current_section = 'contact'\n \n for line in lines:\n line_lower = line.lower().strip()\n \n # Check if line is a section header\n for section, pattern in section_patterns.items():\n if re.match(pattern, line_lower):\n current_section = section\n break\n \n sections[current_section] += line + '\\n'\n \n return sections\n\nresume = parse_resume('resume.pdf')\nprint(\"Skills:\", resume['skills'])\n```\n\n## Limitations\n\n- Cannot extract from scanned/image PDFs (use OCR first)\n- Complex layouts may need manual tuning\n- Some PDF encryption types not supported\n- Embedded fonts may affect text extraction\n- No direct PDF editing capability\n\n## Installation\n\n```bash\npip install pdfplumber\n\n# For image debugging (optional)\npip install Pillow\n```\n\n## Resources\n\n- [pdfplumber Documentation](https://github.com/jsvine/pdfplumber)\n- [Table Extraction Guide](https://github.com/jsvine/pdfplumber#extracting-tables)\n- [Visual Debugging](https://github.com/jsvine/pdfplumber#visual-debugging)","attachment_filenames":[],"attachments":[],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"PDF Extraction Skill","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill enables precise extraction of text, tables, and metadata from PDF documents using ","type":"text"},{"text":"pdfplumber","type":"text","marks":[{"type":"strong"}]},{"text":" - the go-to library for PDF data extraction. Unlike basic PDF readers, pdfplumber provides detailed character-level positioning, accurate table detection, and visual debugging.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"How to Use","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Provide the PDF file you want to extract from","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Specify what you need: text, tables, images, or metadata","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"I'll generate pdfplumber code and execute it","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Example prompts:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Extract all tables from this financial report\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Get text from pages 5-10 of this document\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Find and extract the invoice total from this PDF\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Convert this PDF table to CSV/Excel\"","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Domain Knowledge","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"pdfplumber Fundamentals","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"import pdfplumber\n\n# Open PDF\nwith pdfplumber.open('document.pdf') as pdf:\n # Access pages\n first_page = pdf.pages[0]\n \n # Document metadata\n print(pdf.metadata)\n \n # Number of pages\n print(len(pdf.pages))","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"PDF Structure","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"PDF Document\n├── metadata (title, author, creation date)\n├── pages[]\n│ ├── chars (individual characters with position)\n│ ├── words (grouped characters)\n│ ├── lines (horizontal/vertical lines)\n│ ├── rects (rectangles)\n│ ├── curves (bezier curves)\n│ └── images (embedded images)\n└── outline (bookmarks/TOC)","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Text Extraction","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Basic Text","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"with pdfplumber.open('document.pdf') as pdf:\n # Single page\n text = pdf.pages[0].extract_text()\n \n # All pages\n full_text = ''\n for page in pdf.pages:\n full_text += page.extract_text() or ''","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Advanced Text Options","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# With layout preservation\ntext = page.extract_text(\n x_tolerance=3, # Horizontal tolerance for grouping\n y_tolerance=3, # Vertical tolerance\n layout=True, # Preserve layout\n x_density=7.25, # Chars per unit width\n y_density=13 # Chars per unit height\n)\n\n# Extract words with positions\nwords = page.extract_words(\n x_tolerance=3,\n y_tolerance=3,\n keep_blank_chars=False,\n use_text_flow=False\n)\n\n# Each word includes: text, x0, top, x1, bottom, etc.\nfor word in words:\n print(f\"{word['text']} at ({word['x0']}, {word['top']})\")","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Character-Level Access","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# Get all characters\nchars = page.chars\n\nfor char in chars:\n print(f\"'{char['text']}' at ({char['x0']}, {char['top']})\")\n print(f\" Font: {char['fontname']}, Size: {char['size']}\")","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Table Extraction","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Basic Table Extraction","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"with pdfplumber.open('report.pdf') as pdf:\n page = pdf.pages[0]\n \n # Extract all tables\n tables = page.extract_tables()\n \n for i, table in enumerate(tables):\n print(f\"Table {i+1}:\")\n for row in table:\n print(row)","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Advanced Table Settings","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# Custom table detection\ntable_settings = {\n \"vertical_strategy\": \"lines\", # or \"text\", \"explicit\"\n \"horizontal_strategy\": \"lines\",\n \"explicit_vertical_lines\": [], # Custom line positions\n \"explicit_horizontal_lines\": [],\n \"snap_tolerance\": 3,\n \"snap_x_tolerance\": 3,\n \"snap_y_tolerance\": 3,\n \"join_tolerance\": 3,\n \"edge_min_length\": 3,\n \"min_words_vertical\": 3,\n \"min_words_horizontal\": 1,\n \"intersection_tolerance\": 3,\n \"text_tolerance\": 3,\n \"text_x_tolerance\": 3,\n \"text_y_tolerance\": 3,\n}\n\ntables = page.extract_tables(table_settings)","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Table Finding","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# Find tables (without extracting)\ntable_finder = page.find_tables()\n\nfor table in table_finder:\n print(f\"Table at: {table.bbox}\") # (x0, top, x1, bottom)\n \n # Extract specific table\n data = table.extract()","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Visual Debugging","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# Create visual debug image\nim = page.to_image(resolution=150)\n\n# Draw detected objects\nim.draw_rects(page.chars) # Character bounding boxes\nim.draw_rects(page.words) # Word bounding boxes\nim.draw_lines(page.lines) # Lines\nim.draw_rects(page.rects) # Rectangles\n\n# Save debug image\nim.save('debug.png')\n\n# Debug tables\nim.reset()\nim.debug_tablefinder()\nim.save('table_debug.png')","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Cropping and Filtering","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Crop to Region","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# Define bounding box (x0, top, x1, bottom)\nbbox = (0, 0, 300, 200)\n\n# Crop page\ncropped = page.crop(bbox)\n\n# Extract from cropped area\ntext = cropped.extract_text()\ntables = cropped.extract_tables()","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Filter by Position","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# Filter characters by region\ndef within_bbox(obj, bbox):\n x0, top, x1, bottom = bbox\n return (obj['x0'] >= x0 and obj['x1'] \u003c= x1 and\n obj['top'] >= top and obj['bottom'] \u003c= bottom)\n\nbbox = (100, 100, 400, 300)\nfiltered_chars = [c for c in page.chars if within_bbox(c, bbox)]","type":"text"}]},{"type":"heading","attrs":{"level":4},"content":[{"text":"Filter by Font","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"# Get text by font\ndef extract_by_font(page, font_name):\n chars = [c for c in page.chars if font_name in c['fontname']]\n return ''.join(c['text'] for c in chars)\n\n# Extract bold text (often \"Bold\" in font name)\nbold_text = extract_by_font(page, 'Bold')\n\n# Extract by size\nlarge_chars = [c for c in page.chars if c['size'] > 14]","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Metadata and Structure","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"with pdfplumber.open('document.pdf') as pdf:\n # Document metadata\n meta = pdf.metadata\n print(f\"Title: {meta.get('Title')}\")\n print(f\"Author: {meta.get('Author')}\")\n print(f\"Created: {meta.get('CreationDate')}\")\n \n # Page info\n for i, page in enumerate(pdf.pages):\n print(f\"Page {i+1}: {page.width} x {page.height}\")\n print(f\" Rotation: {page.rotation}\")","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Best Practices","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Debug Visually","type":"text","marks":[{"type":"strong"}]},{"text":": Use ","type":"text"},{"text":"to_image()","type":"text","marks":[{"type":"code_inline"}]},{"text":" to understand PDF structure","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tune Table Settings","type":"text","marks":[{"type":"strong"}]},{"text":": Adjust tolerances for your specific PDF","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Handle Scanned PDFs","type":"text","marks":[{"type":"strong"}]},{"text":": Use OCR first (this skill is for native text)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Process Page by Page","type":"text","marks":[{"type":"strong"}]},{"text":": For large PDFs, avoid loading all at once","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check for Text","type":"text","marks":[{"type":"strong"}]},{"text":": Some PDFs are images - verify text exists","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Common Patterns","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Extract All Tables to DataFrames","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"import pandas as pd\n\ndef pdf_tables_to_dataframes(pdf_path):\n \"\"\"Extract all tables from PDF as pandas DataFrames.\"\"\"\n dfs = []\n \n with pdfplumber.open(pdf_path) as pdf:\n for i, page in enumerate(pdf.pages):\n tables = page.extract_tables()\n \n for j, table in enumerate(tables):\n if table and len(table) > 1:\n # First row as header\n df = pd.DataFrame(table[1:], columns=table[0])\n df['_page'] = i + 1\n df['_table'] = j + 1\n dfs.append(df)\n \n return dfs","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Extract Specific Region","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"def extract_invoice_amount(pdf_path):\n \"\"\"Extract amount from typical invoice layout.\"\"\"\n with pdfplumber.open(pdf_path) as pdf:\n page = pdf.pages[0]\n \n # Search for \"Total\" and get nearby numbers\n words = page.extract_words()\n \n for i, word in enumerate(words):\n if 'total' in word['text'].lower():\n # Look at next few words\n for next_word in words[i+1:i+5]:\n text = next_word['text'].replace(',', '').replace('

PDF Extraction Skill Overview This skill enables precise extraction of text, tables, and metadata from PDF documents using pdfplumber - the go-to library for PDF data extraction. Unlike basic PDF readers, pdfplumber provides detailed character-level positioning, accurate table detection, and visual debugging. How to Use 1. Provide the PDF file you want to extract from 2. Specify what you need: text, tables, images, or metadata 3. I'll generate pdfplumber code and execute it Example prompts: - "Extract all tables from this financial report" - "Get text from pages 5-10 of this document" - "Find…

, '')\n try:\n return float(text)\n except ValueError:\n continue\n \n return None","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Multi-column Layout","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"def extract_columns(page, num_columns=2):\n \"\"\"Extract text from multi-column layout.\"\"\"\n width = page.width\n col_width = width / num_columns\n \n columns = []\n for i in range(num_columns):\n x0 = i * col_width\n x1 = (i + 1) * col_width\n \n cropped = page.crop((x0, 0, x1, page.height))\n columns.append(cropped.extract_text())\n \n return columns","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Examples","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example 1: Financial Report Table Extraction","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"import pdfplumber\nimport pandas as pd\n\ndef extract_financial_tables(pdf_path):\n \"\"\"Extract tables from financial report and save to Excel.\"\"\"\n \n with pdfplumber.open(pdf_path) as pdf:\n all_tables = []\n \n for page_num, page in enumerate(pdf.pages):\n # Debug: save table visualization\n im = page.to_image()\n im.debug_tablefinder()\n im.save(f'debug_page_{page_num+1}.png')\n \n # Extract tables\n tables = page.extract_tables({\n \"vertical_strategy\": \"lines\",\n \"horizontal_strategy\": \"lines\",\n \"snap_tolerance\": 5,\n })\n \n for table in tables:\n if table and len(table) > 1:\n # Clean data\n clean_table = []\n for row in table:\n clean_row = [cell.strip() if cell else '' for cell in row]\n clean_table.append(clean_row)\n \n df = pd.DataFrame(clean_table[1:], columns=clean_table[0])\n df['Source Page'] = page_num + 1\n all_tables.append(df)\n \n # Save to Excel with multiple sheets\n with pd.ExcelWriter('extracted_tables.xlsx') as writer:\n for i, df in enumerate(all_tables):\n df.to_excel(writer, sheet_name=f'Table_{i+1}', index=False)\n \n return all_tables\n\ntables = extract_financial_tables('annual_report.pdf')\nprint(f\"Extracted {len(tables)} tables\")","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example 2: Invoice Data Extraction","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"import pdfplumber\nimport re\nfrom datetime import datetime\n\ndef extract_invoice_data(pdf_path):\n \"\"\"Extract structured data from invoice PDF.\"\"\"\n \n data = {\n 'invoice_number': None,\n 'date': None,\n 'total': None,\n 'line_items': []\n }\n \n with pdfplumber.open(pdf_path) as pdf:\n page = pdf.pages[0]\n text = page.extract_text()\n \n # Extract invoice number\n inv_match = re.search(r'Invoice\\s*#?\\s*:?\\s*(\\w+)', text, re.IGNORECASE)\n if inv_match:\n data['invoice_number'] = inv_match.group(1)\n \n # Extract date\n date_match = re.search(r'Date\\s*:?\\s*(\\d{1,2}[/-]\\d{1,2}[/-]\\d{2,4})', text)\n if date_match:\n data['date'] = date_match.group(1)\n \n # Extract total\n total_match = re.search(r'Total\\s*:?\\s*\\$?([\\d,]+\\.?\\d*)', text, re.IGNORECASE)\n if total_match:\n data['total'] = float(total_match.group(1).replace(',', ''))\n \n # Extract line items from table\n tables = page.extract_tables()\n for table in tables:\n if table and any('description' in str(row).lower() for row in table[:2]):\n # Found line items table\n for row in table[1:]: # Skip header\n if row and len(row) >= 3:\n data['line_items'].append({\n 'description': row[0],\n 'quantity': row[1] if len(row) > 1 else None,\n 'amount': row[-1]\n })\n \n return data\n\ninvoice = extract_invoice_data('invoice.pdf')\nprint(f\"Invoice #{invoice['invoice_number']}\")\nprint(f\"Total: ${invoice['total']}\")","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example 3: Resume/CV Parser","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"import pdfplumber\n\ndef parse_resume(pdf_path):\n \"\"\"Extract structured sections from resume.\"\"\"\n \n with pdfplumber.open(pdf_path) as pdf:\n full_text = ''\n for page in pdf.pages:\n full_text += (page.extract_text() or '') + '\\n'\n \n # Common resume sections\n sections = {\n 'contact': '',\n 'summary': '',\n 'experience': '',\n 'education': '',\n 'skills': ''\n }\n \n # Split by common headers\n import re\n section_patterns = {\n 'summary': r'(summary|objective|profile)',\n 'experience': r'(experience|employment|work history)',\n 'education': r'(education|academic)',\n 'skills': r'(skills|competencies|technical)'\n }\n \n lines = full_text.split('\\n')\n current_section = 'contact'\n \n for line in lines:\n line_lower = line.lower().strip()\n \n # Check if line is a section header\n for section, pattern in section_patterns.items():\n if re.match(pattern, line_lower):\n current_section = section\n break\n \n sections[current_section] += line + '\\n'\n \n return sections\n\nresume = parse_resume('resume.pdf')\nprint(\"Skills:\", resume['skills'])","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Limitations","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cannot extract from scanned/image PDFs (use OCR first)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Complex layouts may need manual tuning","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Some PDF encryption types not supported","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Embedded fonts may affect text extraction","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No direct PDF editing capability","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Installation","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"pip install pdfplumber\n\n# For image debugging (optional)\npip install Pillow","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Resources","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pdfplumber Documentation","type":"text","marks":[{"type":"link","attrs":{"href":"https://github.com/jsvine/pdfplumber","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Table Extraction Guide","type":"text","marks":[{"type":"link","attrs":{"href":"https://github.com/jsvine/pdfplumber#extracting-tables","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Visual Debugging","type":"text","marks":[{"type":"link","attrs":{"href":"https://github.com/jsvine/pdfplumber#visual-debugging","title":null}}]}]}]}]}]},"metadata":{"mcp":{"tools":["extract_text_from_pdf","extract_tables_from_pdf"],"server":"office-mcp"},"date":"2026-11-02","name":"pdf-extraction","tags":["pdf","extraction","text","tables"],"author":"claude-office-skills","models":{"compatible":["claude-3-5-sonnet","gpt-4","gpt-4o"],"recommended":["claude-sonnet-4","claude-opus-4"]},"source":{"stars":558,"repo_name":"skills","origin_url":"https://github.com/claude-office-skills/skills/blob/HEAD/pdf-extraction/SKILL.md","repo_owner":"claude-office-skills","body_sha256":"fd89439447039ae8068814eb2d6e05409930bd22172121934bcbc099e2d8b16a","cluster_key":"e1cf096d573c136291cea0fe3edc3d2157de82c2a0dfbca2194ca5c426d4bd56","clean_bundle":{"format":"clean-skill-bundle-v1","source":"claude-office-skills/skills/pdf-extraction/SKILL.md","text_bytes":0,"source_commit":"9c4c7d5cd2813a8936bf2c9fdb174ea883b85a11","skills_sh_rank":2621,"attachment_count":0,"text_attachments":0,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"pdf-extraction/SKILL.md","import_metadata":{"date":"2026-11-02","author":"claude-office-skills","version":"1.0","category":"documents-office","category_label":"Documents"},"exact_dupes_collapsed_into_this":0},"license":"MIT","version":"1.0","category":"documents-office","languages":["en","zh"],"department":"All","import_tag":"skills-sh-top20k-2026-11","description":"Extract text, tables, and metadata from PDFs using pdfplumber","capabilities":["text_extraction","table_extraction","data_mining"]}},"renderedAt":1793666747867}

PDF Extraction Skill Overview This skill enables precise extraction of text, tables, and metadata from PDF documents using pdfplumber - the go-to library for PDF data extraction. Unlike basic PDF readers, pdfplumber provides detailed character-level positioning, accurate table detection, and visual debugging. How to Use 1. Provide the PDF file you want to extract from 2. Specify what you need: text, tables, images, or metadata 3. I'll generate pdfplumber code and execute it Example prompts: - "Extract all tables from this financial report" - "Get text from pages 5-10 of this document" - "Find…