[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6XEMSWRR7R9SBNDSBNSHJB4":3,"skill-same:01M6XEMSWRR7R9SBNDSBNSHJB4":72},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":25,"publishedAt":46,"linkOnly":47,"markdownContent":48,"markdownBody":49,"frontMatter":50,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":13,"repositoryHtmlUrl":54,"repositoryHomepageUrl":6,"ownerHtmlUrl":55,"ownerBlogUrl":6,"ownerDescription":56,"updatedAt":57,"install":58,"resources":71},"01M6XEMSWRR7R9SBNDSBNSHJB4","pdf",null,"ALWAYS use this skill instead of the Read tool for PDF files. The Read tool cannot extract PDF tables properly. Use this skill when: (1) Reading ANY PDF file, (2) Extracting tables from PDFs, (3) Converting PDF tables to pandas DataFrames, (4) Processing multi-page PDFs","Waaaalnut\u002Fskillsbench","Waaaalnut","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F103995656?v=4","01M6XCS9K1V51EY3JMB7DGMX24","01M6XCS9Q4WPW88W62C55G1H44",0,"Apache-2.0","https:\u002F\u002Fgithub.com\u002FWaaaalnut\u002Fskillsbench\u002Fblob\u002Fmain\u002Ftasks\u002Fsales-pivot-analysis\u002Fenvironment\u002Fskills\u002Fpdf\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000002","文档处理","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000013","分析与可视化",[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"PDF","dataframes","when","multi-page","extracting tables","for","reading","extracting","multi","processing","extract pdf","pdf tables","files","use","extract","read","page","tool","file","pandas","2026-11-10 10:12:30",false,"---\nname: pdf\ndescription: \"ALWAYS use this skill instead of the Read tool for PDF files. The Read tool cannot extract PDF tables properly. Use this skill when: (1) Reading ANY PDF file, (2) Extracting tables from PDFs, (3) Converting PDF tables to pandas DataFrames, (4) Processing multi-page PDFs\"\n---\n\n# PDF Processing Guide\n\n## IMPORTANT: Do NOT Use the Read Tool for PDFs\n\n**The Read tool cannot properly extract tabular data from PDFs.** It will only show you a limited preview of the first page's text content, missing most of the data.\n\nFor PDF files, especially multi-page PDFs with tables:\n- **DO**: Use `pdfplumber` as shown in this skill\n- **DO NOT**: Use the Read tool to view PDF contents\n\nIf you need to extract data from a PDF, write Python code using pdfplumber. This is the only reliable way to get complete table data from all pages.\n\n## Overview\n\nExtract text and tables from PDF documents using Python libraries.\n\n## Table Extraction with pdfplumber\n\npdfplumber is the recommended library for extracting tables from PDFs.\n\n### Basic Table Extraction\n\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for page in pdf.pages:\n        tables = page.extract_tables()\n        for table in tables:\n            print(table)  # List of lists\n```\n\n### Convert to pandas DataFrame\n\n```python\nimport pdfplumber\nimport pandas as pd\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    page = pdf.pages[0]  # First page\n    tables = page.extract_tables()\n\n    if tables:\n        # First row is usually headers\n        table = tables[0]\n        df = pd.DataFrame(table[1:], columns=table[0])\n        print(df)\n```\n\n### Extract All Tables from Multi-Page PDF\n\n```python\nimport pdfplumber\nimport pandas as pd\n\nall_tables = []\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for page in pdf.pages:\n        tables = page.extract_tables()\n        for table in tables:\n            if table and len(table) > 1:  # Has data\n                df = pd.DataFrame(table[1:], columns=table[0])\n                all_tables.append(df)\n\n# Combine if same structure\nif all_tables:\n    combined = pd.concat(all_tables, ignore_index=True)\n```\n\n## Text Extraction\n\n### Full Page Text\n\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    text = \"\"\n    for page in pdf.pages:\n        text += page.extract_text() + \"\\n\"\n```\n\n### Text with Layout Preserved\n\n```python\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    page = pdf.pages[0]\n    text = page.extract_text(layout=True)\n```\n\n## Common Patterns\n\n### Extract Multiple Tables and Create Mappings\n\nWhen a PDF contains multiple related tables (possibly spanning multiple pages), extract from ALL pages and build lookup dictionaries:\n\n```python\nimport pdfplumber\nimport pandas as pd\n\ncategory_map = {}      # CategoryID -> CategoryName\nproduct_map = {}       # ProductID -> (ProductName, CategoryID)\n\nwith pdfplumber.open(\"catalog.pdf\") as pdf:\n    for page_num, page in enumerate(pdf.pages):\n        tables = page.extract_tables()\n\n        for table in tables:\n            if not table or len(table) \u003C 2:\n                continue\n\n            # Check first row to identify table type\n            header = [str(cell).strip() if cell else '' for cell in table[0]]\n\n            # Determine if first row is header or data (continuation page)\n            if 'CategoryID' in header and 'CategoryName' in header:\n                # Categories table with header\n                for row in table[1:]:\n                    if row and len(row) >= 2 and row[0]:\n                        cat_id = int(row[0].strip())\n                        cat_name = row[1].strip()\n                        category_map[cat_id] = cat_name\n\n            elif 'ProductID' in header and 'ProductName' in header:\n                # Products table with header\n                for row in table[1:]:\n                    if row and len(row) >= 3 and row[0]:\n                        try:\n                            prod_id = int(row[0].strip())\n                            prod_name = row[1].strip()\n                            cat_id = int(row[2].strip())\n                            product_map[prod_id] = (prod_name, cat_id)\n                        except (ValueError, AttributeError):\n                            continue\n            else:\n                # Continuation page (no header) - check if it's product data\n                for row in table:\n                    if row and len(row) >= 3 and row[0]:\n                        try:\n                            prod_id = int(row[0].strip())\n                            prod_name = row[1].strip()\n                            cat_id = int(row[2].strip())\n                            product_map[prod_id] = (prod_name, cat_id)\n                        except (ValueError, AttributeError):\n                            continue\n\n# Build final mapping: ProductID -> CategoryName\nproduct_to_category_name = {\n    pid: category_map[cat_id]\n    for pid, (name, cat_id) in product_map.items()\n}\n# {1: 'Beverages', 2: 'Beverages', 3: 'Condiments', ...}\n```\n\n**Important:** Always iterate over ALL pages (`for page in pdf.pages`) - tables often span multiple pages, and continuation pages may not have headers.\n\n### Clean Extracted Table Data\n\n```python\nimport pdfplumber\nimport pandas as pd\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    table = pdf.pages[0].extract_tables()[0]\n    df = pd.DataFrame(table[1:], columns=table[0])\n\n    # Clean whitespace\n    df = df.apply(lambda x: x.str.strip() if x.dtype == \"object\" else x)\n\n    # Remove empty rows\n    df = df.dropna(how='all')\n\n    # Rename columns if needed\n    df.columns = df.columns.str.strip()\n```\n\n### Handle Missing Headers\n\n```python\n# If table has no header row\ntable = pdf.pages[0].extract_tables()[0]\ndf = pd.DataFrame(table)\ndf.columns = ['Col1', 'Col2', 'Col3', 'Col4']  # Assign manually\n```\n\n## Quick Reference\n\n| Task | Code |\n|------|------|\n| Open PDF | `pdfplumber.open(\"file.pdf\")` |\n| Get pages | `pdf.pages` |\n| Extract tables | `page.extract_tables()` |\n| Extract text | `page.extract_text()` |\n| Table to DataFrame | `pd.DataFrame(table[1:], columns=table[0])` |\n\n## Troubleshooting\n\n- **Empty table**: Try `page.extract_tables(table_settings={...})` with custom settings\n- **Merged cells**: Tables with merged cells may extract incorrectly\n- **Scanned PDFs**: Use OCR (pytesseract) for image-based PDFs\n- **No tables found**: Check if content is actually a table or styled text\n","# PDF Processing Guide\n\n## IMPORTANT: Do NOT Use the Read Tool for PDFs\n\n**The Read tool cannot properly extract tabular data from PDFs.** It will only show you a limited preview of the first page's text content, missing most of the data.\n\nFor PDF files, especially multi-page PDFs with tables:\n- **DO**: Use `pdfplumber` as shown in this skill\n- **DO NOT**: Use the Read tool to view PDF contents\n\nIf you need to extract data from a PDF, write Python code using pdfplumber. This is the only reliable way to get complete table data from all pages.\n\n## Overview\n\nExtract text and tables from PDF documents using Python libraries.\n\n## Table Extraction with pdfplumber\n\npdfplumber is the recommended library for extracting tables from PDFs.\n\n### Basic Table Extraction\n\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for page in pdf.pages:\n        tables = page.extract_tables()\n        for table in tables:\n            print(table)  # List of lists\n```\n\n### Convert to pandas DataFrame\n\n```python\nimport pdfplumber\nimport pandas as pd\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    page = pdf.pages[0]  # First page\n    tables = page.extract_tables()\n\n    if tables:\n        # First row is usually headers\n        table = tables[0]\n        df = pd.DataFrame(table[1:], columns=table[0])\n        print(df)\n```\n\n### Extract All Tables from Multi-Page PDF\n\n```python\nimport pdfplumber\nimport pandas as pd\n\nall_tables = []\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for page in pdf.pages:\n        tables = page.extract_tables()\n        for table in tables:\n            if table and len(table) > 1:  # Has data\n                df = pd.DataFrame(table[1:], columns=table[0])\n                all_tables.append(df)\n\n# Combine if same structure\nif all_tables:\n    combined = pd.concat(all_tables, ignore_index=True)\n```\n\n## Text Extraction\n\n### Full Page Text\n\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    text = \"\"\n    for page in pdf.pages:\n        text += page.extract_text() + \"\\n\"\n```\n\n### Text with Layout Preserved\n\n```python\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    page = pdf.pages[0]\n    text = page.extract_text(layout=True)\n```\n\n## Common Patterns\n\n### Extract Multiple Tables and Create Mappings\n\nWhen a PDF contains multiple related tables (possibly spanning multiple pages), extract from ALL pages and build lookup dictionaries:\n\n```python\nimport pdfplumber\nimport pandas as pd\n\ncategory_map = {}      # CategoryID -> CategoryName\nproduct_map = {}       # ProductID -> (ProductName, CategoryID)\n\nwith pdfplumber.open(\"catalog.pdf\") as pdf:\n    for page_num, page in enumerate(pdf.pages):\n        tables = page.extract_tables()\n\n        for table in tables:\n            if not table or len(table) \u003C 2:\n                continue\n\n            # Check first row to identify table type\n            header = [str(cell).strip() if cell else '' for cell in table[0]]\n\n            # Determine if first row is header or data (continuation page)\n            if 'CategoryID' in header and 'CategoryName' in header:\n                # Categories table with header\n                for row in table[1:]:\n                    if row and len(row) >= 2 and row[0]:\n                        cat_id = int(row[0].strip())\n                        cat_name = row[1].strip()\n                        category_map[cat_id] = cat_name\n\n            elif 'ProductID' in header and 'ProductName' in header:\n                # Products table with header\n                for row in table[1:]:\n                    if row and len(row) >= 3 and row[0]:\n                        try:\n                            prod_id = int(row[0].strip())\n                            prod_name = row[1].strip()\n                            cat_id = int(row[2].strip())\n                            product_map[prod_id] = (prod_name, cat_id)\n                        except (ValueError, AttributeError):\n                            continue\n            else:\n                # Continuation page (no header) - check if it's product data\n                for row in table:\n                    if row and len(row) >= 3 and row[0]:\n                        try:\n                            prod_id = int(row[0].strip())\n                            prod_name = row[1].strip()\n                            cat_id = int(row[2].strip())\n                            product_map[prod_id] = (prod_name, cat_id)\n                        except (ValueError, AttributeError):\n                            continue\n\n# Build final mapping: ProductID -> CategoryName\nproduct_to_category_name = {\n    pid: category_map[cat_id]\n    for pid, (name, cat_id) in product_map.items()\n}\n# {1: 'Beverages', 2: 'Beverages', 3: 'Condiments', ...}\n```\n\n**Important:** Always iterate over ALL pages (`for page in pdf.pages`) - tables often span multiple pages, and continuation pages may not have headers.\n\n### Clean Extracted Table Data\n\n```python\nimport pdfplumber\nimport pandas as pd\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    table = pdf.pages[0].extract_tables()[0]\n    df = pd.DataFrame(table[1:], columns=table[0])\n\n    # Clean whitespace\n    df = df.apply(lambda x: x.str.strip() if x.dtype == \"object\" else x)\n\n    # Remove empty rows\n    df = df.dropna(how='all')\n\n    # Rename columns if needed\n    df.columns = df.columns.str.strip()\n```\n\n### Handle Missing Headers\n\n```python\n# If table has no header row\ntable = pdf.pages[0].extract_tables()[0]\ndf = pd.DataFrame(table)\ndf.columns = ['Col1', 'Col2', 'Col3', 'Col4']  # Assign manually\n```\n\n## Quick Reference\n\n| Task | Code |\n|------|------|\n| Open PDF | `pdfplumber.open(\"file.pdf\")` |\n| Get pages | `pdf.pages` |\n| Extract tables | `page.extract_tables()` |\n| Extract text | `page.extract_text()` |\n| Table to DataFrame | `pd.DataFrame(table[1:], columns=table[0])` |\n\n## Troubleshooting\n\n- **Empty table**: Try `page.extract_tables(table_settings={...})` with custom settings\n- **Merged cells**: Tables with merged cells may extract incorrectly\n- **Scanned PDFs**: Use OCR (pytesseract) for image-based PDFs\n- **No tables found**: Check if content is actually a table or styled text\n",{"name":5,"description":7},"main","7eeb258ada72b7f58119b0e7a2c00ea89d9beedd","tasks\u002Fsales-pivot-analysis\u002Fenvironment\u002Fskills\u002Fpdf","https:\u002F\u002Fgithub.com\u002FWaaaalnut\u002Fskillsbench","https:\u002F\u002Fgithub.com\u002FWaaaalnut","student of Zhejiang University","2026-04-21 23:16:23",{"source":8,"skillName":5,"commands":59,"prompt":69,"zipAvailable":70},[60,63,66],{"tool":61,"command":62},"npx","npx skills add Waaaalnut\u002Fskillsbench --skill pdf",{"tool":64,"command":65},"bunx","bunx skills add Waaaalnut\u002Fskillsbench --skill pdf",{"tool":67,"command":68},"pnpm","pnpm dlx skills add Waaaalnut\u002Fskillsbench --skill pdf","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FWaaaalnut\u002Fskillsbench\u002Fblob\u002Fmain\u002Ftasks\u002Fsales-pivot-analysis\u002Fenvironment\u002Fskills\u002Fpdf\u002FSKILL.md",true,[],[73,87,102,126,148,165],{"skillNo":74,"name":75,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":83,"publishedAt":46},"01M6XEWMJ6VY3ZC53MPDCPG3GH","data-reconciliation","https:\u002F\u002Fgithub.com\u002FWaaaalnut\u002Fskillsbench\u002Fblob\u002Fmain\u002Ftasks\u002Fxlsx-recover-data\u002Fenvironment\u002Fskills\u002Fdata-reconciliation\u002FSKILL.md",[78],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[84,85,86],"data reconciliation","reconciliation","data",{"skillNo":88,"name":89,"nameZh":6,"description":90,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":46},"01M6XEW8MNPMF1KRXV6ATGFRQF","speech-to-text","Transcribe video to timestamped text using Whisper tiny model (pre-installed).","https:\u002F\u002Fgithub.com\u002FWaaaalnut\u002Fskillsbench\u002Fblob\u002Fmain\u002Ftasks\u002Fvideo-tutorial-indexer\u002Fenvironment\u002Fskills\u002Fspeech-to-text\u002FSKILL.md",[],[94,95,96,97,98,99,100,101],"speech","text","speech to text","transcribe video","whisper","model","Video","transcribe",{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":111,"publishedAt":46},"01M6XEW3FQZP0T1RKQQJFXVY9T","video-processor","Process videos by removing segments and concatenating remaining parts. Use when you need to remove detected pauses\u002Fopenings from videos, create highlight reels, or batch process segment removals using ffmpeg filter_complex.","https:\u002F\u002Fgithub.com\u002FWaaaalnut\u002Fskillsbench\u002Fblob\u002Fmain\u002Ftasks\u002Fvideo-silence-remover\u002Fenvironment\u002Fskills\u002Fvideo-processor\u002FSKILL.md",[108],{"categoryNo":109,"categoryName":110,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000016","图像与多媒体",[100,112,113,114,115,116,28,117,118,119,120,121,122,123,124,39,125],"processor","video processor","batch","create","reels","parts","segments","process","videos","you","segment","filter","ffmpeg","remove",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":133,"publishedAt":46},"01M6XEVXJ5KZ0NTY3XZKRY4AS1","silence-detector","Detect initial silence segments in audio\u002Fvideo using energy-based analysis. Use when you need to find low-energy periods at the start of recordings (title slides, setup time, pre-roll silence).","https:\u002F\u002Fgithub.com\u002FWaaaalnut\u002Fskillsbench\u002Fblob\u002Fmain\u002Ftasks\u002Fvideo-silence-remover\u002Fenvironment\u002Fskills\u002Fsilence-detector\u002FSKILL.md",[132],{"categoryNo":109,"categoryName":110,"taxonomyType":20,"taxonomyTypeDesc":21},[134,135,136,137,28,121,138,139,140,141,142,118,143,144,100,145,146,147,39],"detector","silence detector","title","slides","time","energy","at","recordings","detect","find","Audio","analysis","start","setup",{"skillNo":149,"name":150,"nameZh":6,"description":151,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":152,"categories":153,"keywords":154,"publishedAt":46},"01M6XEVT3NGRN1FT7JPMAPXS6M","segment-combiner","Combine multiple segment detection results into a unified list. Use when you need to merge segments from different detectors, prepare removal lists for video processing, or consolidate detection outputs.","https:\u002F\u002Fgithub.com\u002FWaaaalnut\u002Fskillsbench\u002Fblob\u002Fmain\u002Ftasks\u002Fvideo-silence-remover\u002Fenvironment\u002Fskills\u002Fsegment-combiner\u002FSKILL.md",[],[122,155,100,156,157,158,159,31,28,160,161,118,121,35,162,39,163,164],"segment combiner","detection","prepare","merge","video processing","outputs","combine","consolidate","results","list",{"skillNo":166,"name":167,"nameZh":6,"description":168,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":169,"categories":170,"keywords":174,"publishedAt":46},"01M6XEVMPVASGS2KX86QK4FMT7","report-generator","Generate compression reports for video processing. Use when you need to create structured JSON reports with duration statistics, compression ratios, and segment details after video processing.","https:\u002F\u002Fgithub.com\u002FWaaaalnut\u002Fskillsbench\u002Fblob\u002Fmain\u002Ftasks\u002Fvideo-silence-remover\u002Fenvironment\u002Fskills\u002Freport-generator\u002FSKILL.md",[171],{"categoryNo":172,"categoryName":173,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000034","行政与办公人员",[175,176,177,122,28,31,121,178,35,179,180,181,39,159,182,100,183,184,115],"generator","report generator","report","with","statistics","structured","reports","json","compression","generate"]