
简介这是一份面向家庭烹饪爱好者与新手厨师的实用型菜谱合集聚焦家常炒菜核心技法与高频菜品解决日常下厨选菜难、火候难控、调味不准等痛点。资源为单个PDF文件675KB内含80道经典小炒菜谱每道均详述食材处理、分步操作、火候要点及调味比例并穿插酸辣土豆丝、红烧茄子、地三鲜、干煸豆角等典型示例的工艺拆解覆盖蔬菜、肉类、蛋类、豆制品等多类食材搭配逻辑。内容系统整合烹调技巧、食材选择、锅具运用、安全规范及文化常识兼顾实操性与知识性适合零基础入门或提升炒菜稳定性。目前已有749人下载学习是快速掌握中式快炒逻辑、建立个人菜谱库的高性价比参考资料。1. 为什么一份结构清晰的 PDF 菜谱比手机 App 更适合厨房实操在灶火正旺、油锅滋滋作响的三分钟里没人会去解锁手机、划开 App、等加载、再点开「青椒肉丝」——更别说网络卡顿或权限弹窗。而一份本地 PDF 菜谱双击即开、翻页零延迟、横屏竖屏自由切、不耗电不联网手指沾着酱油也能精准滑到第 37 页的「鱼香茄子」步骤图。这不是怀旧是人机交互在高温高湿高干扰厨房场景下的物理降噪PDF 的静态结构、固定排版、无后台进程、跨设备一致性天然适配「看一眼→抓一把→下锅→再看一眼」的烹饪节律。本篇聚焦的不是菜谱内容本身而是如何把《80个家常炒菜菜谱.pdf》真正用起来——从快速定位、高效检索、离线标注到按食材/技法/耗时做二次组织最终让这份 PDF 成为灶台边可响应、可延伸、可进化的数字厨具。适合每天做饭但反感碎片化信息的上班族、需要批量打印分发给学员的烹饪讲师以及想把纸质菜谱数字化归档的家庭用户。2. 用 PDF 工具链实现「秒级定位语义检索」的实操路径2.1 为什么不能只靠 Adobe Reader 自带搜索PDF 内置搜索仅匹配字符序列对「蒜末」「蒜蓉」「蒜泥」视作不同词无法识别「小火煸香」和「中火煸出香味」的语义等价性更无法关联「豆瓣酱」「郫县豆瓣」「红油豆瓣」这类同物异名。实测在《80个家常炒菜菜谱.pdf》中搜索「辣椒」漏掉所有写成「二荆条」「小米辣」「杭椒」的条目搜索「炒」字则混入「炒锅」「炒勺」「快炒」等无关结果。根本症结在于该 PDF 是扫描图像型Scan-based还是文字可选型Text-selectable用pdfinfo命令一查便知pdfinfo 80个家常炒菜菜谱.pdf | grep -i pages\|format\|creator提示若输出中Pages:后为数字但Creator:显示Adobe Scan或CamScanner基本可判定为图像 PDF若Creator:为LibreOffice或Microsoft Word则大概率含原生文本层。2.2 图像 PDF 的 OCR 文本重建Tesseract Python 脚本化处理对扫描版 PDF必须先 OCR 提取文本。跳过 GUI 工具用命令行保证可复现性。安装 Tesseractv5.3及中文语言包# Ubuntu/Debian sudo apt install tesseract-ocr tesseract-ocr-chi-sim # macOS (Homebrew) brew install tesseract brew install tesseract-lang核心脚本pdf_ocr.py实现分页 OCR 与结构化输出#!/usr/bin/env python3 import os import subprocess import fitz # PyMuPDF from pathlib import Path def ocr_pdf(input_pdf: str, output_txt: str): doc fitz.open(input_pdf) full_text for page_num in range(len(doc)): # 将每页转为高分辨率 PNG300dpi 避免 OCR 模糊 pix doc[page_num].get_pixmap(dpi300) img_path ftemp_page_{page_num:03d}.png pix.save(img_path) # 调用 Tesseract 进行中文 OCR result subprocess.run( [tesseract, img_path, stdout, -l, chi_sim], capture_outputTrue, textTrue, encodingutf-8 ) if result.returncode 0: full_text f\n--- Page {page_num 1} ---\n{result.stdout.strip()}\n # 清理临时文件 Path(img_path).unlink(missing_okTrue) with open(output_txt, w, encodingutf-8) as f: f.write(full_text) print(fOCR 完成文本已保存至 {output_txt}) if __name__ __main__: ocr_pdf(80个家常炒菜菜谱.pdf, 80_cookbook_ocr.txt)参数说明-l chi_sim指定简体中文模型dpi300是 OCR 准确率临界值低于 200dpi 会导致「葱」误识为「忽」、「蚝」误识为「毫」fitzPyMuPDF比pdf2image更轻量且支持直接渲染。2.3 构建可检索的结构化索引用 SQLite 存储菜名、食材、步骤关键词将 OCR 文本解析为结构化记录关键在于识别菜谱的隐式结构。观察《80个家常炒菜菜谱.pdf》典型格式【菜名】→ 独占一行含「炒」「爆」「熘」等动词主料→ 后接逗号分隔的食材列表辅料→ 同上做法→ 后续为编号步骤1. ... 2. ...Python 解析脚本parse_recipes.pyimport sqlite3 import re def parse_ocr_text(ocr_file: str, db_file: str): conn sqlite3.connect(db_file) conn.execute( CREATE TABLE IF NOT EXISTS recipes ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, main_ingredients TEXT, aux_ingredients TEXT, steps TEXT, keywords TEXT ) ) with open(ocr_file, r, encodingutf-8) as f: content f.read() # 按「【菜名】」分割不同菜谱 recipe_blocks re.split(r【([^】])】, content) for i in range(1, len(recipe_blocks), 2): if i 1 len(recipe_blocks): break name recipe_blocks[i].strip() block recipe_blocks[i 1] # 提取主料、辅料、做法 main_match re.search(r主料[:]\s*([^\n]), block) aux_match re.search(r辅料[:]\s*([^\n]), block) steps_match re.search(r做法[:]\s*(.?)(?\n(?:【|\Z)), block, re.DOTALL) main_ing main_match.group(1).strip() if main_match else aux_ing aux_match.group(1).strip() if aux_match else steps steps_match.group(1).strip() if steps_match else # 生成关键词菜名主料核心动词炒/煸/爆 keywords f{name} {main_ing} if 炒 in steps or 煸 in steps or 爆 in steps: keywords 炒制 conn.execute( INSERT INTO recipes (name, main_ingredients, aux_ingredients, steps, keywords) VALUES (?, ?, ?, ?, ?), (name, main_ing, aux_ing, steps, keywords) ) conn.commit() conn.close() print(f解析完成共存入 {len(recipe_blocks)//2} 道菜谱) if __name__ __main__: parse_ocr_text(80_cookbook_ocr.txt, cookbook.db)注意re.DOTALL让.匹配换行符确保捕获多行「做法」(?\n(?:【|\Z))使用前瞻断言避免截断下一个菜名。执行后生成cookbook.db可用sqlite3 cookbook.db进入交互式查询。2.4 在终端中实现「自然语言式」查询用 FTS5 全文检索加速SQLite 的 FTS5 扩展专为中文分词优化比 LIKE 模糊匹配快两个数量级。启用并建索引-- 进入 SQLite 命令行 sqlite3 cookbook.db -- 启用 FTS5 并创建虚拟表 CREATE VIRTUAL TABLE recipes_fts USING fts5( name, main_ingredients, aux_ingredients, steps, keywords ); -- 将原表数据导入虚拟表 INSERT INTO recipes_fts SELECT name, main_ingredients, aux_ingredients, steps, keywords FROM recipes; -- 查询示例找含「猪肉」且做法含「腌制」的菜 SELECT name FROM recipes_fts WHERE recipes_fts MATCH 猪肉 AND 腌制; -- 查询示例找主料含「豆腐」或「豆干」的菜OR 逻辑 SELECT name FROM recipes_fts WHERE recipes_fts MATCH 豆腐 OR 豆干;提示FTS5 默认使用 Unicode 分词器对中文单字、词组均有效MATCH语法支持AND/OR/NOT及短语红烧肉加引号精确匹配。查询响应时间稳定在 5ms 内远超 PDF 查找的 2~8 秒。3. 基于 PDF 元数据与书签的「零点击导航」系统搭建3.1 手动添加书签的局限性与自动化替代方案多数 PDF 阅读器允许手动添加书签但《80个家常炒菜菜谱.pdf》含 80 道菜逐页添加效率极低且无法关联食材或技法。真正的解法是用 Python 动态生成符合 PDF 标准的书签树并注入到原文件中。核心工具是PyPDF2v3.0或更稳定的pypdfv4.0pip install pypdf脚本add_bookmarks.py读取 SQLite 中的菜名与页码映射生成层级书签from pypdf import PdfReader, PdfWriter import sqlite3 def add_bookmarks_to_pdf(pdf_path: str, db_path: str, output_path: str): reader PdfReader(pdf_path) writer PdfWriter() # 复制所有页面 for page in reader.pages: writer.add_page(page) # 连接数据库获取菜名与页码需提前在 OCR 时记录页码 conn sqlite3.connect(db_path) cursor conn.cursor() cursor.execute(SELECT name, id FROM recipes ORDER BY id) recipes cursor.fetchall() conn.close() # 创建根书签 root writer.add_outline_item(家常炒菜目录, 0) # 为每道菜添加子书签假设菜名在对应页首行 for idx, (name, recipe_id) in enumerate(recipes): # 简单估算页码每页约 1.2 道菜80 道 / 67 页 ≈ 1.2实际应从 OCR 日志提取 estimated_page min(idx * 1.2, len(reader.pages) - 1) writer.add_outline_item(name, int(estimated_page), parentroot) with open(output_path, wb) as f: writer.write(f) print(f书签已添加输出至 {output_path}) if __name__ __main__: add_bookmarks_to_pdf(80个家常炒菜菜谱.pdf, cookbook.db, 80_cookbook_bookmarked.pdf)注意真实场景中需在 OCR 阶段记录每道菜的起始页码如通过检测「【菜名】」所在页此处用估算值演示逻辑。生成的书签在 Adobe Acrobat、Foxit、macOS 预览中均可展开折叠点击直达目标页。3.2 利用 PDF 元数据实现「系统级分类」让 Finder/Explorer 按食材过滤Windows 资源管理器和 macOS Finder 均支持按 PDF 元数据如作者、主题、关键词筛选文件。将 SQLite 中的高频食材写入 PDF 元数据即可实现系统级标签from pypdf import PdfReader, PdfWriter def inject_metadata(pdf_path: str, output_path: str, keywords: list): reader PdfReader(pdf_path) writer PdfWriter() for page in reader.pages: writer.add_page(page) # 设置元数据 writer.add_metadata({ /Title: 80个家常炒菜菜谱, /Author: 家庭厨房整理, /Subject: 家常炒菜技术文档, /Keywords: , .join(keywords) # 例如 [猪肉, 青椒, 鸡蛋, 豆腐] }) with open(output_path, wb) as f: writer.write(f) # 从数据库提取前 10 高频主料 conn sqlite3.connect(cookbook.db) cursor conn.cursor() cursor.execute( SELECT main_ingredients, COUNT(*) as cnt FROM recipes GROUP BY main_ingredients ORDER BY cnt DESC LIMIT 10 ) top_ingredients [row[0] for row in cursor.fetchall()] conn.close() inject_metadata(80_cookbook_bookmarked.pdf, 80_cookbook_tagged.pdf, top_ingredients)提示在 macOS Finder 中按CmdShiftF调出高级搜索选择「种类」为 PDF「其他」中添加「关键词」条件输入「猪肉」即可筛出所有含猪肉的菜谱 PDFWindows 用户在资源管理器搜索框输入keywords:猪肉同理。3.3 书签与元数据协同构建「双通道导航」工作流书签解决「纵向快速跳转」从目录到具体菜元数据解决「横向批量筛选」从全部 PDF 中挑出某类食材。二者结合形成闭环晨间备菜在 Finder 中搜索keywords:鸡肉批量打开 12 个含鸡肉的 PDF用书签快速对比「宫保鸡丁」「辣子鸡丁」「香菇滑鸡」的做法差异教学演示教师将80_cookbook_tagged.pdf发给学生学生用自带阅读器的书签面板直接展开「素菜类」分支无需滚动查找应急场景冰箱只剩「鸡蛋」和「番茄」在终端执行sqlite3 cookbook.db SELECT name FROM recipes_fts WHERE recipes_fts MATCH 鸡蛋 AND 番茄;两秒得答案「番茄炒蛋」「番茄鸡蛋汤」。这种设计不增加用户操作负担所有增强功能均内嵌于 PDF 文件本身脱离任何特定软件或网络环境。4. 针对厨房场景的 PDF 优化技巧防油污、单手操作与离线标注4.1 屏幕防油污模式用 CSS 覆盖 PDF 查看器的默认样式在 Chrome/Firefox 中打开 PDF 时白底黑字易被灶台油渍反光干扰。通过浏览器扩展如 Stylus注入自定义 CSS强制 PDF 查看器使用深色模式/* 应用于 chrome-extension://oemmndcbldboiebfnladdacbdfmadadm/pdf_viewer.css */ body { background-color: #1a1a1a !important; } #viewer { background-color: #1a1a1a !important; } .page { background-color: #2d2d2d !important; box-shadow: 0 0 10px rgba(0,0,0,0.5) !important; } .textLayer span { color: #e0e0e0 !important; text-shadow: 0 0 2px rgba(0,0,0,0.8) !important; }提示此 CSS 仅作用于浏览器内置 PDF 查看器不影响文件本身box-shadow增加页面立体感降低油膜造成的视觉模糊text-shadow确保浅灰文字在暗背景下仍清晰可辨。4.2 单手翻页的物理交互优化键盘快捷键与触控板手势绑定厨房操作中一手持锅铲一手点鼠标极不现实。必须将翻页操作映射到最易触发的硬件MacBook 触控板在「系统设置→触控板→滚动与缩放」中启用「三指向上/下」为「显示调度中心」和「显示程序坞」改用「四指左/右」为「切换全屏应用」再通过 BetterTouchTool 将「四指左滑」绑定为CmdShiftLeft Arrow上一页Windows 笔记本用 PowerToys 的 Keyboard Manager将Caps Lock J映射为CtrlPageUp上一页Caps Lock K映射为CtrlPageDown下一页——Caps Lock键大且位置固定戴手套亦可按压通用方案在 PDF 阅读器中设置「空格键下一页」「Shift空格上一页」这是所有主流阅读器Sumatra PDF、Okular、Preview的默认行为无需额外配置。4.3 离线标注同步用 Git 版本控制管理你的私有笔记在 PDF 上手写标注如「少放糖」「孩子爱吃」后如何确保这些个性化信息不随文件更新丢失答案是将标注导出为独立 JSON 文件用 Git 管理版本。以 Okular 为例其标注保存在~/.local/share/okular/docdata/下的.xml文件中。转换脚本export_annotations.pyimport xml.etree.ElementTree as ET import json from pathlib import Path def export_okular_annotations(pdf_path: str, output_json: str): # Okular 的标注文件名是 PDF 路径的 SHA256 哈希 pdf_hash hashlib.sha256(pdf_path.encode()).hexdigest() annot_path Path.home() / .local/share/okular/docdata / f{pdf_hash}.xml if not annot_path.exists(): print(未找到 Okular 标注文件) return tree ET.parse(annot_path) root tree.getroot() annotations [] for annot in root.findall(.//annotation): annot_data { page: annot.find(page).text, type: annot.find(type).text, content: annot.find(content).text if annot.find(content) is not None else , color: annot.find(color).text if annot.find(color) is not None else #000000 } annotations.append(annot_data) with open(output_json, w, encodingutf-8) as f: json.dump(annotations, f, ensure_asciiFalse, indent2) print(f标注已导出至 {output_json}) if __name__ __main__: export_okular_annotations(80_cookbook_tagged.pdf, my_cookbook_notes.json)提示将my_cookbook_notes.json加入 Git 仓库每次修改标注后git commit -m 标记宫保鸡丁减辣即可回溯任意版本的私人笔记。重装系统或换电脑时只需git clone仓库并导入 JSON 到新 Okular 实例。4.4 打印优化生成 A5 折页版适配厨房磁吸白板为方便贴在厨房白板上需将 PDF 转为 A5 尺寸、双页拼版即一页 PDF 含左右两个 A5 页面并添加裁切线。用pdfjam实现# 安装 pdfjam基于 LaTeX sudo apt install texlive-extra-utils # Ubuntu brew install pdfjam # macOS # 生成 A5 双栏拼版带 3mm 裁切线 pdfjam --a5paper --landscape --scale 0.95 \ --trim 3mm 3mm 3mm 3mm --clip true \ --outfile 80_cookbook_a5.pdf \ 80_cookbook_tagged.pdf参数说明--scale 0.95防止内容溢出--trim添加裁切区域--clip true启用裁切线渲染。打印后沿虚线裁开得到 80 张 A5 卡片背面涂磁粉即可吸附于不锈钢灶台侧板。当油星溅到屏幕时你不再需要擦屏——因为视线已习惯深色背景当锅里咕嘟作响时你不用放下锅铲找手机——因为食指轻敲触控板就翻到下一页当想复刻上周那道惊艳的「鱼香肉丝」时你不必凭记忆翻 30 页——因为sqlite3 cookbook.db SELECT steps FROM recipes WHERE name鱼香肉丝;的输出就在终端里静静等待。这份 PDF 不再是静态文档而是经由工具链激活的厨房操作系统。本文还有配套的精品资源点击获取