Skills Plugins MCP Prompt Model 博客 我的中心
内容创作 #data #image

pdf

Read, extract (text/tables), create, merge/split/rotate, watermark, encrypt, fill, and render-to-image .pdf files. Use whenever the user uploads a .pdf or asks to produce, edit, or pull data out of one.

DeepseekModel 官方收录技能 质量 优秀 · 90 v1.0.0

获取

https://deepseekmodel.com/api/download.php?id=hkuds-deeptutor-deeptutor-skills-builtin-pdf-skill-md&format=skill
下载 .skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name pdf description Read, extract (text/tables), create, merge/split/rotate, watermark, encrypt, fill, and render-to-image .pdf files. Use whenever the user uploads a .pdf or asks to produce, edit, or pull data out of one. tags ["tool","office"] requires {"sandbox":"shell"} PDF Work PDFs in the sandbox with preinstalled Python libs. Pick the library by task: Extract text/tables/layout/word-coordinates → pdfplumber ; quick raw text or page ops → pypdf . Merge / split / rotate / crop / watermark / encrypt / metadata → pypdf . Fill forms → pypdf (fillable AcroForm fields) or annotation overlay (flat forms). Create from scratch → reportlab . Use exec with complete Python source ( language: python ). Prefer creating, reopening, and validating the PDF in one call; later calls can revise the same relative filename. Follow the turn's User workspace instructions for locating inputs, output boundaries, and presenting the finished file. Preserve an explicitly requested quantity (such as 500 words) and verify the count in the output before finishing. If execution fails or the artifact is missing, diagnose stderr/root cause and change strategy; do not retry identical code or reduce the requested scope without asking. Extract text and tables (pdfplumber) import pdfplumber with pdfplumber. open ( "in.pdf" ) as pdf: for i, page in enumerate (pdf.pages, 1 ): print ( f"--- page {i} ---" ) print (page.extract_text() or "" ) # layout-aware text for t in page.extract_tables(): # list of tables; each is list[row] for row in t: print (row) Tables → Excel (one worksheet per table): import pdfplumber from openpyxl import Workbook workbook = Workbook() workbook.remove(workbook.active) table_number = 0 with pdfplumber. open ( "in.pdf" ) as pdf: for page_number, page in enumerate (pdf.pages, 1 ): for table in page.extract_tables(): if not table: continue table_number += 1 sheet = workbook.create_sheet( f"p {page_number} _table {table_number} " [: 31 ]) for row in table: sheet.append([cell or "" for cell in row]) if table_number: workbook.save( "tables.xlsx" ) Messy tables: pass strategies, or crop a region with page.within_bbox((x0, top, x1, bottom)) first: ts = { "vertical_strategy" : "lines" , "horizontal_strategy" : "lines" , "snap_tolerance" : 3 , "intersection_tolerance" : 15 , } page.extract_tables(ts) For very large PDFs where you only need raw text, pypdf 's page.extract_text() is lighter. Scanned / image-only PDFs (be honest) If extract_text() returns empty or garbage (e.g. (cid:NN) runs) the page is scanned. No OCR engine (tesseract) is installed and network is off , so you cannot recover that text. Say so plainly and stop — do not fabricate content or attempt pip install . Merge / split / rotate / crop / metadata (pypdf) from pypdf import PdfReader, PdfWriter # Merge w = PdfWriter() for f in [ "a.pdf" , "b.pdf" ]: for p in PdfReader(f).pages: w.add_page(p) w.write( "merged.pdf" ) # Split: one file per page r = PdfReader( "in.pdf" ) for i, p in enumerate (r.pages, 1 ): w = PdfWriter() w.add_page(p) w.write( f"page_ {i} .pdf" ) # Rotate page 0 by 90 degrees clockwise r = PdfReader( "in.pdf" ) w = PdfWriter() r.pages[ 0 ].rotate( 90 ) w.add_page(r.pages[ 0 ]) w.write( "rotated.pdf" ) Metadata : PdfReader("in.pdf").metadata ( .title , .author , ...). Crop : set page.mediabox.left/bottom/right/top (points, origin y=0 at bottom). Encrypt : w = PdfWriter(clone_from=PdfReader("in.pdf")); w.encrypt("userpw", "ownerpw"); w.write("enc.pdf") . Decrypt : r = PdfReader("enc.pdf"); r.decrypt("pw") if r.is_encrypted , then read/copy pages. Watermark (stamp one page over every page): from pypdf import PdfReader, PdfWriter wm = PdfReader( "stamp.pdf" ).pages[ 0 ] r = PdfReader( "in.pdf" ) w = PdfWriter() for p in r.pages: p.merge_page(wm) w.add_page(p) w.write( "stamped.pdf" ) Create PDFs (reportlab) Flowing document (preferred for text/reports/tables — handles pagination): from reportlab.lib.pagesizes import letter from reportlab.lib.styles import getSampleStyleSheet from reportlab.lib import colors from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle styles = getSampleStyleSheet() story = [ Paragraph( "Report Title" , styles[ "Title" ]), Spacer( 1 , 12 ), Paragraph( "Body text. " * 20 , styles[ "Normal" ]), ] data = [[ "Product" , "Q1" , "Q2" ], [ "Widgets" , "120" , "135" ]] tbl = Table(data) tbl.setStyle( TableStyle( [ ( "BACKGROUND" , ( 0 , 0 ), (- 1 , 0 ), colors.grey), ( "TEXTCOLOR" , ( 0 , 0 ), (- 1 , 0 ), colors.whitesmoke), ( "GRID" , ( 0 , 0 ), (- 1 , - 1 ), 0.5 , colors.black), ] ) ) story += [Spacer( 1 , 12 ), tbl] SimpleDocTemplate( "out.pdf" , pagesize=letter).build(story) Absolute placement (labels at fixed coordinates): use canvas.Canvas("out.pdf", pagesize=letter) , c.drawString(x, y, "...") (origin bottom-left, points), c.showPage() per page, c.save() . Non-Latin text (Chinese / Japanese / Korean, Cyrillic, …) reportlab's built-in fonts (Helvetica/Times/Courier) carry zero CJK glyphs , so any 中文/日本語/한국어 renders as empty boxes (□) baked permanently into the PDF. reportlab never auto-discovers system fonts — you MUST register a font that has the glyphs and set it on every style. Whenever the document may contain non-Latin text, register a CJK font first (it also covers Latin, so it is safe to use as the only font): import os from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont def register_cjk_font ( name= "CJK" ): # TrueType ONLY — reportlab cannot embed CFF/OpenType outlines, so a .otf # like Noto Sans CJK fails with "postscript outlines are not supported". for path in [ "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc" , # Linux sandbox (fonts-wqy-zenhei) "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc" , "/System/Library/Fonts/STHeiti Light.ttc" , # macOS "/System/Library/Fonts/Hiragino Sans GB.ttc" , "/System/Library/Fonts/Supplemental/Songti.ttc" , "/System/Library/Fonts/Supplemental/Arial Unicode.ttf" , "C:/Windows/Fonts/msyh.ttc" , # Windows ]: if os.path.exists(path): try : pdfmetrics.registerFont(TTFont(name, path, subfontIndex= 0 )) return name except Exception: continue raise RuntimeError( "No CJK-capable TrueType font found — do not emit tofu; say so." ) font = register_cjk_font() styles = getSampleStyleSheet() for s in styles.byName.values(): # make the CJK font the default everywhere s.fontName = font # Tables don't read the stylesheet — set the font in the TableStyle too: # ("FONTNAME", (0, 0), (-1, -1), font) # Canvas: c.setFont(font, size) before every drawString. If register_cjk_font raises (no font on the host), do not ship a tofu PDF — tell the user the sandbox lacks a CJK font instead of producing garbage. Gotcha: even with a good font, reportlab still needs markup for subscripts/superscripts. In Paragraph use Paragraph("H<sub>2</sub>O", styles["Normal"]) , x<super>2</super> . Markdown/HTML → PDF needs an external converter ( soffice / pandoc ) that is usually absent — command -v soffice / command -v pandoc and degrade to building the PDF directly with reportlab if neither is present. Fill forms (pypdf) First detect whether the PDF has real fillable (AcroForm) fields: from pypdf import PdfReader fields = PdfReader( "form.pdf" ).get_fields() print ( "fillable" if fields else "flat (no fields)" ) Fillable — inspect field names/types, then fill and write: from pypdf import PdfReader, PdfWriter r = PdfReader( "form.pdf" ) for name, f in r.get_fields().items(): print (name, f.get( "/FT" ), f.get( "/_States_" )) # /Tx text, /Btn checkbox/radio, /Ch choice w = PdfWriter(clone_from=r) values = { "first_name" : "Bart" , "agree" : "/Yes" } # checkbox/radio: use its on-state, NOT True/False for page in w.pages: w.update_page_form_field_values(page, values, auto_regenerate= False ) w.set_need_appearances_writer( True ) # force viewers to render the values w.write( "filled.pdf" ) Checkbox/radio values are on-state strings, not booleans — read the field's /_States_ (e.g. /Yes , /On ); /Off clears it. Flat form (no fields) — overlay text with FreeText annotations at PDF coordinates. Get real coordinates from the layout with pdfplumber instead of guessing: import pdfplumber with pdfplumber. open ( "form.pdf" ) as pdf: pg = pdf.pages[ 0 ] for wd in pg.extract_words(): # each has x0, top, x1, bottom (TOP-left origin!) print (wd[ "text" ], wd[ "x0" ], wd[ "top" ]) for rc in pg.rects: # small squares are likely checkboxes print ( "rect" , rc[ "x0" ], rc[ "top" ], rc[ "x1" ], rc[ "bottom" ]) pdfplumber top is measured from the page top; pypdf rects are bottom-left, so convert: pdf_y = page_height - top . Place text just right of the matching label: from pypdf import PdfReader, PdfWriter from pypdf.annotations import FreeText r = PdfReader( "form.pdf" ) w = PdfWriter() w.append(r) h = float (r.pages[ 0 ].mediabox.height) top = 700 # pdfplumber 'top' of the label's row w.add_annotation( page_number= 0 , annotation=FreeText( text= "Smith" , rect=( 255 , h - top - 14 , 720 , h - top), # (x0, y0, x1, y1) font= "Helvetica" , font_size= "10pt" , font_color= "000000" , border_color= None , background_color= None , ), ) w.write( "filled.pdf" ) Verify: re-open the output and re-read get_fields() values (fillable) or re-extract text (overlay) to confirm the values landed. Page → image rendering (PyMuPDF) PyMuPDF (imported as fitz , preinstalled) rasterizes pages — useful to inspect a PDF visually or to hand a page to an image-capable step. No external tools needed (poppler / pdf2image are absent; don't reach for them). import fitz # PyMuPDF doc = fitz. open ( "in.pdf" ) for i, page in enumerate (doc, 1 ): page.get_pixmap(dpi= 150 ).save( f"page_ {i} .png" ) # higher dpi = sharper + larger fitz also extracts text ( page.get_text() ) and can render a sub-region via page.get_pixmap(clip=fitz.Rect(x0, y0, x1, y1)) . It does not OCR — a rendered scanned page is still just pixels (see Scanned PDFs above).
Agent 识别该技能的关键词,点击任意一个即可复制。

该技能未提供触发词。

下载的 .skill 包内含以下字段。
字段 说明
format格式标识(skill/v1)
skill_id技能唯一 ID
name技能名称
version版本号
description技能描述
category所属分类(数组)
trigger_words触发词列表
tags标签列表
source来源标识
source_url来源链接(本页地址)
exported_at导出时间(每次下载生成)
system_prompt系统提示词正文
model_config模型参数:provider / model / temperature / max_tokens / top_p
examples示例
install_guide各平台导入说明(Coze / Dify / Claude / 自定义框架)
同一份技能可按不同平台格式导出。
.skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用 下载
.skillpro 增强格式,额外含脚本 / 工具 / 依赖 / 钩子占位 下载
.json 纯 JSON 导出,只含 system_prompt 与模型参数 下载
Coze 带 frontmatter 的 Markdown,Coze 平台导入用 下载
Dify Dify DSL,创建应用后直接导入 下载

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。