简介:Photoshop基础简答题整理,面向正在学习计算机图形图像处理、准备课程考试或技能认证的读者,也可作为教师出题参考。内容覆盖矢量图与位图的特点、路径的理解、蒙板的类型与应用、图像选择与处理流程、计算机图形和图像概念的辨析、CMYK与RGB色彩模式区别、羽化原理及实现、图层合并的三种命令等核心考点,每题均给出条理清晰、可直接背诵的参考答案,能帮助读者快速建立知识框架并查漏补缺。资源为单个PDF文档,共1个文件,文件大小仅127KB,轻巧便捷,适合在手机或电脑上随时打开阅读,作为考前冲刺或碎片化复习的随身资料。目前已有51人浏览学习。如果你需要一份PS简答题标准答案,这份整理可直接参考使用。
1. 一份带“(2)”的ps简答题PDF:先弄清楚它为什么搜不到、转不动
说实话,这类文件名末尾带着“(2)”的“ps简答题.pdf”,十有八九是从网盘或班级群重复下载出来的副本,这里的ps基本就是Photoshop的简称,不是PostScript;PDF里装的是Photoshop基础概念问答,比如什么是图层蒙版、通道有哪几种、色彩模式怎么切换。它最让人头疼的地方不是内容看不懂,而是被做成了“能看不能搜”的黑匣子:双击能翻页,想复制题干却乱码,想转word又到处是页眉页脚,打印出来还发虚。这篇笔记就围绕“把这份PDF变成能搜索、能改题、能组卷的干净题库”展开,适合准备PS考试的同学,也适合培训机构拿旧PDF重新做讲义的人。网上那些ps破解版、ps免费安装包压缩包风险很高,尽量别碰;很多ps全家桶、ps笔刷素材分享包里都夹着这类题库PDF,真正值得整理成结构化数据的恰恰是这一份。
2. 先分辨PDF是文字版还是图片版:三步探测法决定用pdftotext还是OCR
2.1 为什么会提不动:PDF的文本层与图片层是两回事
PDF和Word不一样,它不是“一个文档”,更像一个排版容器。容器里既可能有真正的文字对象,也可能只有一张张位图。判断一份PDF能不能直接提取,核心就看它有没有文本层。文字版PDF通常由Word直接打印生成,选中文字完全正常;图片版PDF多来自扫描仪或拍照,整页就是一张图,复制出来永远是空的。很多PS简答题PDF其实介于两者之间:前半部分转自Word,后半部分是扫描补充页,这种混合型最坑,因为纯文本提取会漏题。
先跑一段页面统计脚本,把每一页的文本长度和图片数量打印出来,这是整个处理流程的地基:
import fitz doc = fitz.open("ps简答题 (2).pdf") for i, page in enumerate(doc, 1): text = page.get_text().strip() imgs = page.get_images(full=True) print(f"第{i:>3}页 | 文本长度={len(text):>5} | 图片数={len(imgs)}")逻辑说明:enumerate(doc, 1)让页码从1开始;get_text()抓取该页的文本层内容,strip()之后用长度判断这页有没有文字;get_images(full=True)返回页面引用的图片对象数量。注意它只查xref引用,不会解压整张图,几十页的文件几秒就能跑完。跑完脚本,把输出对照下面这张表,基本能确定这份PDF属于哪一类。
| 页面特征 | 判定类型 | 提取策略 |
|---|---|---|
| 文本长度明显大于0,图片数少或为0 | 文字版 | pdftotext直接提取 |
| 文本长度接近0,图片数大于等于1 | 图片版 | 渲染页面后OCR |
| 前若干页有文本,后面若干页文本为空 | 混合型 | 先提取文本,再对空页OCR补缺 |
不要凭阅读器里“看起来是文字”就认定能提取。字体子集不全时页面照样渲染得清清楚楚,复制出来却是一堆乱码,这也是我每次都要先跑统计、而不是直接双击复制的原因。PDF解析的第一原则就是:先看数据,再选工具。
2.2 文字版优先:pdftotext加-layout,保住编号缩进
判定为文字版后,最常见做法不是打开Python慢慢解析,而是先用系统里的poppler工具集一把梭。pdftotext是poppler-utils自带的命令行工具,Linux和Windows的WSL里都有,处理本地PDF零依赖、速度快,还不会像某些在线工具那样把文件传出去。题库这类内部资料,我一般不出本机处理。
pdftotext -layout -enc UTF-8 "ps简答题 (2).pdf" ps.txt wc -l ps.txt head -n 20 ps.txt逻辑说明:-layout是关键参数,它按页面原始版式保留空格和换行。对简答题这种“题目编号顶格、答案另起一段”的排版,没有-layout时pdftotext会把“1.”和题干挤到同一行后面,导致后面切题的正则不好写;加上之后,每道题的边界基本清晰。-enc UTF-8指定输出编码为UTF-8,否则中文在Windows记事本里会变成乱码。
跑完之后head看前20行,确认题号和答案标记是否完整。如果某个中间页的文本长度突然变成0,说明它是扫描图,回到2.1的表格走混合型处理。如果你更习惯Python生态,用pdfplumber也可以按坐标输出字符,但速度比pdftotext慢不少,几十页的题库没必要;我的习惯是先命令行工具摸底,再决定要不要上Python。
2.3 图片版兜底:渲染300dpi再OCR,参数怎么设
如果探测结果是大半页面没有文本层,那就只能走OCR。做OCR的首要原则是能用库就别用在线网站。PS考题里常出现的“图层”“蒙版”“通道”都是常见中文词,本地模型完全能搞定,没必要把文件传到别人的服务器上。工具链我一般用PyMuPDF做渲染、Tesseract做识别;公司里如果团队是.NET技术栈,用Tesseract的C#封装或现成的“C# OCR PDF”方向组件也能达到同样效果,思路完全一致:先按分辨率渲染,再交给识别引擎。
import fitz import pytesseract from PIL import Image doc = fitz.open("ps简答题 (2).pdf") for i, page in enumerate(doc, 1): # 只处理没有文本层的页,有文本层的不动 if len(page.get_text().strip()) > 0: continue pix = page.get_pixmap(dpi=300) pix.save(f"page_{i:03d}.png") img = Image.open(f"page_{i:03d}.png") txt = pytesseract.image_to_string(img, lang="chi_sim+eng", config="--psm 6") print(f"=== 第{i}页 ===") print(txt)逻辑说明:先判断这页有没有文本层,有就跳过,没有才渲染。dpi=300是印刷级清晰度,中文小五号字也能识别;再往上调600只会让图片变大、识别变慢,对简答题这种版面没有明显收益。--psm 6让Tesseract按“整块文本”识别,而不是按单行或单字,对一整页题干效果最好;lang写成chi_sim+eng,是因为题干里混着“Photoshop”“RGB”“Alpha”这类英文词,只开中文会把这些词转成拼音或直接丢字。
跑完把识别文本和pdftotext的结果按页码拼接,就得到覆盖全部页的完整文本。还有一个坑先提一下:Tesseract不做deskew,遇到歪斜扫描页会识别出一堆乱码。先按角度把图转正再识别,比对着参数死磕更高效。数据清洗到这里就算完成了,下一章是真正的重头戏:把一整块文本切成一道题。
3. 把PDF文本切成一道道题:编号切题、答案剥离与模糊去重
3.1 先摸清题目编号规律,再写切题正则
拿到完整文本,下一步是把一坨文本拆成“一道题加一段答案”的结构。这一步很多人翻车,原因是他们一上来就写一个大正则,想一次匹配所有题号。实际上PDF排版千奇百怪,有的题号是“1.”,有的是“2、”,有的是“1)”,还有的写“第1题”。直接写万能正则会误伤题干里出现的数字,比如“RGB三通道”里的“3”。常见做法是先写几个候选模式,分别数一下命中次数,用数据决定用哪个。
import re txt = open("ps.txt", encoding="utf-8").read() candidates = [ r"(?m)^\s*(\d{1,3})[\.、)]\s*", r"(?m)^\s*第\s*(\d{1,3})\s*题", ] for i, pat in enumerate(candidates, 1): hits = re.findall(pat, txt) print(f"模式{i}: 命中{len(hits)}次 示例={hits[:5]}")逻辑说明:(?m)开启多行模式,^才能匹配每一行的开头;^\s*允许题号前面有缩进;(\d{1,3})限定1到3位数字;[\.、)]覆盖最常见的三种分隔符。re.findall只返回数字组,所以结果是一串题号列表。哪种模式命中次数接近你肉眼数的题目数量,就用哪种;如果两种都不合理,回到文本里看实际排版,八成是题号后面跟的是全角空格或制表符,把\s*改成[ \t\u3000]*再说。
这一步花五分钟看数据,比反复试正则省一小时。真正干过PDF解析的人都明白:题号格式永远是第一个要摸清的事实,而不是第一件要猜的事情。
3.2 切题与答案分离:按“问/答”标记重组题目结构
确定模式后就可以正式切题了。切题的原则是“先找起点,再做内容切割”:用re.finditer找出所有题号的位置,相邻两个题号之间的内容就是一道题的完整文本;拿到题目内容后,再在内部找“答案/答”标记,把题干和答案拆开。
import re def clean_headfoot(text): text = re.sub(r"第\s*\d{1,3}\s*页\s*共\s*\d{1,3}\s*页", "", text) text = re.sub(r"Photoshop\s*简答题题库", "", text) text = re.sub(r"\n{3,}", "\n\n", text) return text.strip() def split_questions(text, pattern): text = clean_headfoot(text) matches = list(re.finditer(pattern, text)) questions = [] for idx, m in enumerate(matches): end = matches[idx + 1].start() if idx + 1 < len(matches) else len(text) body = text[m.end():end].strip() if not body: continue if re.search(r"答案\s*[::]", body): q, a = re.split(r"答案\s*[::]", body, maxsplit=1) elif re.search(r"(?m)^\s*答\s*[::]", body): q, a = re.split(r"(?m)^\s*答\s*[::]", body, maxsplit=1) else: q, a = body, "" questions.append((m.group(1), q.strip(), a.strip())) return questions逻辑说明:clean_headfoot先干掉页码和页眉,否则“第1页 共10页”里的“1”会被当成题号。re.finditer返回所有题号的match对象,idx + 1的start()就是下一题起点,刚好作为本道题的结束位置;最后一道题用len(text)收尾。答案分离用了两个正则:第一种匹配行内“答案:”,第二种匹配行首“答:”,两种PDF格式都能覆盖。maxsplit=1保证答案正文里如果再出现“答案”二字,也不会被二次切开。
如果原PDF根本没有答案,else分支保留整段当题干,答案留空,后面组卷时只印题干也不会报错。做完这一步,你会得到一个结构化的列表,每个元素是(题号, 题干, 答案),这就是后续一切处理的原料。
3.3 模糊去重:用difflib按题干前20字判重
PDF整合自多个来源后,经常出现同一道题换了标点、加了空格就重复的情况。精确字符串去重解决不了这种问题,用difflib的SequenceMatcher算相似度是性价比最高的方案。题库规模就几十道题,完全没必要上向量库。
from difflib import SequenceMatcher def is_dup(a, b, threshold=0.85): if not a or not b: return False sa, sb = a[:20], b[:20] return SequenceMatcher(None, sa, sb).ratio() >= threshold unique = [] for no, q, a in questions: if not any(is_dup(q, old[1]) for old in unique): unique.append((no, q, a))逻辑说明:is_dup只比较每题题干的前20个字符,因为简答题的题干前20字基本把考点定死了,答案区长短不该参与判重;SequenceMatcher的ratio()返回0到1的相似度,0.85阈值适合这种短文本。阈值太低了会合并掉“图层蒙版的作用”和“图层蒙版的原理”这类容易误判的题,太高又漏掉带错别字的重复题。跑完如果发现去重后的题目数明显低于预期,把threshold提到0.9再看一遍命中列表,确认没有误杀后再批量执行。
这里还有个习惯:尽量别用去重结果覆盖原始文本,先另存一份,万一手滑删多了还能有后悔药。
3.4 导出CSV与Markdown:让“转word”不再依赖PDF编辑器
很多同事拿到PDF第一反应是丢进pdf编辑器另存成docx,结果页眉页脚、扫描页、答案样式全搅在一起,改错一道题要删半天。常见做法其实是先把题库结构化成CSV或Markdown,再用Word或WPS打开导出,PDF只当数据源用。这样既绕开了pdf编辑器的排版僵局,也方便后续按标签抽题。
import csv rows = [(i, q, a) for i, (no, q, a) in enumerate(unique, 1)] with open("ps_题库.csv", "w", newline="", encoding="utf-8-sig") as f: w = csv.writer(f) w.writerow(["题号", "题干", "答案"]) w.writerows(rows) with open("ps_题库.md", "w", encoding="utf-8") as f: for i, q, a in rows: f.write(f"### {i}. {q}\n\n{a}\n\n")逻辑说明:CSV用utf-8-sig编码,Excel和WPS双击打开中文不会乱码;题号重新自增,是因为去重后原始编号可能有断号,重新编号方便后续抽题时按序号引用。Markdown文件的好处是通用性极强,Typora、VS Code、GitHub都能直接预览,也可以复制进Word调整格式。到这里,任何一份“ps简答题 (2).pdf”都变成了真正属于你自己的结构化题库;下一章讲的是这个过程中最容易反复横跳的坑。
4. 避坑记录:从打开PDF到组卷打印,先排掉这五个坑
4.1 坑一:能看不能复制,复制出来全乱码
现象:PDF阅读器里选中题干正常,Ctrl+C粘贴到记事本却变成一行乱码或者空白。
原因:PDF的字体子集只嵌入了字形数据,没有写入正确的ToUnicode映射。渲染时可以按字形显示,反向查Unicode时却查不到,这是PDF里最典型的玄学问题,跟你电脑装的是哪一版PS软件没有关系。
解决:不要继续跟复制较劲,直接把这一页按2.3的流程渲染成PNG再OCR。识别结果即使有几个错字,也比乱码文本有用;如果只有个别页乱码,其他页正常,就按页码混合处理,乱码页走OCR,正常页走pdftotext。
4.2 坑二:混合型PDF漏题,前面10题有、后面全消失
现象:pdftotext提取出的文本只到第10题,后面的题人间蒸发,题目数量对不上。
原因:后面几页是扫描生成的位图,没有文本层,pdftotext压根提取不到内容。这种“前半Word、后半扫描”的混合PDF在培训机构流出的题库里非常常见。
解决:跑一遍2.1的统计脚本,把“文本长度小于设定阈值”的页单独挑出来OCR,再按页码顺序把两路输出合并,合并主流程示意如下:
# 假定 text_pages[i] 和 ocr_pages[i] 分别来自 pdftotext 与 OCR 结果 full = [] for i, page in enumerate(doc, 1): if len(page.get_text().strip()) > 20: full.append(text_pages[i - 1]) else: full.append(ocr_pages[i - 1])逻辑说明:合并脚本并不复杂,难在阈值设多少。我一般先看统计结果分布,文本长度出现明显断层的那个值就是阈值;比如大部分页在300字以上、扫描页只有几个字符,那就用20当阈值。合并完再检查一次题目数量是否连续,绝大多数漏题都能在这一步被拦下来。
4.3 坑三:导出word后答案跟题干揉在一起
现象:好不容易转出docx,发现每一题的答案都紧跟在题干后面,想给学生发一份只有题目的讲义,还得手工一段段删。
原因:原PDF里的“答案:”标记在pdftotext提取后缩进丢失,变成了题干和答案之间一个普通换行,通用pdf编辑器转word时不会智能分拆。
解决:先按3.2的split_questions把题干和答案拆成两个字段,再分别导出。如果发现原PDF的答案标记是“【答案】”之类的变体,把正则里的答案\s*[::]扩展成(?:答案|答|【答案】)\s*[::]?再跑一次,比在word里手动删快一个数量级。
4.4 坑四:打印发虚、页边距浪费
现象:打印图片型PDF,字迹发毛,边缘像水彩晕开;网页另存的PDF打印时多出页眉,或者每页底部被切掉一块。
原因:页面本身是低分辨率位图,打印机放大打印时只能插值补点,自然发虚。还有一部分PDF来自浏览器“web页面pdf打印”,打印区域按网页版式走了,不是按纸面版式。
解决:打印前用2.3的渲染管线把页面重新输出成300dpi的PDF,或者先把OCR得到的干净文本重新排版成A4再打印。打印对话框里选“实际大小”而不是“适合页面”,背景图形要显示就勾上“打印背景图像”。我自己的教训是,打印前永远先看打印预览的第一页和最后一页,PDF的坑往往藏在首尾。
4.5 坑五:文件名带“(2)”是重复下载,内容却换了版本
现象:同一个“ps简答题.pdf”下载了两次,浏览器自动命名成“ps简答题 (2).pdf”,页数和题号基本一致,但个别题的表述和答案完全不同。复习到考前一天才发现拿的是另外一版。
原因:上传者更新过原文件,浏览器自动加了副本序号。你以为只是重复下载,实际下到的是新版或旧版,文件名完全无法区分。
解决:拿到文件先记指纹,用sha256哈希把版本钉死:
import hashlib raw = open("ps简答题 (2).pdf", "rb").read() print(hashlib.sha256(raw).hexdigest()[:16])逻辑说明:哈希值前16位足够在笔记里做版本标识。我习惯在整理完题库后,把哈希写进题库文件名的前缀,例如20250512_3f2a_ps题库.csv,最近的哈希比文件名可信得多;群里有人发“第19题答案”时,先对一下哈希再讨论,能省掉一晚上的无效争论。
5. 输出端的加分动作:给简答题打标签,十分钟抽出一套模拟卷
5.1 用关键词规则给题干打标签,不需要标注人力
题库整理干净后,下一个高频需求是“按章节复习”或“临时组一套模拟卷”。直接random抽题不够专业,因为PS简答题的考点很集中:图层、蒙版、通道、滤镜、选区、色彩、历史记录、钢笔工具。常见做法是用关键词规则给每道题打标签,先规则跑一轮,再人工抽查几条修正,基本够用。
tags = { "图层": ["图层", "蒙版", "图层样式"], "通道": ["通道", "Alpha", "RGB"], "滤镜": ["滤镜", "锐化", "模糊"], "选区": ["选区", "魔棒", "套索", "羽化"], "色彩": ["色彩", "色相", "饱和度", "明度"], } def tag_of(q): hit = [name for name, keys in tags.items() if any(k in q for k in keys)] return hit if hit else ["基础"] for no, q, a in unique: print(f"{no}. {q[:20]} -> {'/'.join(tag_of(q))}")逻辑说明:tag_of返回列表,所以一道题同时涉及图层和选区时能带两个标签;没有命中关键词的题统一落到“基础”,比如“什么是像素?”这类概念题。这套规则最大的价值不是分类准确,而是可解释——哪个词触发的标签一目了然,后面想调整分类,改字典即可,不用重写逻辑。
5.2 固定随机种子抽题:让同一题库每次抽出的卷子可复现
组卷最怕的是每次跑结果都不一样,学生拿到的模拟卷和老师手里的答案对不上。random.seed能让随机序列固定下来,这是最简单也最容易被忽略的复现手段。
import random from collections import defaultdict random.seed(20250512) buckets = defaultdict(list) for no, q, a in unique: for t in tag_of(q): buckets[t].append((no, q, a)) paper = [] for t in ["图层", "通道", "滤镜", "选区"]: pool = buckets[t] paper += random.sample(pool, min(3, len(pool))) random.shuffle(paper) for idx, (no, q, a) in enumerate(paper, 1): print(f"{idx}. {q}")逻辑说明:random.seed(20250512)是核心,同一个种子下random.sample的抽取路径完全相同,每次运行生成的模拟卷一模一样,方便老师对答案、也方便学生反复练;想换一套卷,把种子改一个数字就行。min(3, len(pool))防止某个标签下题目数量不足时抛异常,少于3题就全取。抽出来的卷子可以按之前的CSV结构输出成“模拟卷.csv”,打印时只留题干,答案列留在自己手里。
验证这套抽题是否健康的方法也很简单:换一个种子再生成一份,对比两份卷子的重复题数。重合率超过30%说明题库太薄,要么补题,要么把每个标签抽题数从3降到2。我自己以前拿到这种带“(2)”的PDF,上来就丢进pdf编辑器转word打印,结果考场上好几道题字迹糊成一片,血泪教训之后才养成“先跑统计脚本、再决定流程”的习惯。后来把题库做成结构化数据,最大的收益不只是省了一次打印,而是这份题库能一直复用:换版本、加新题、按章抽卷,都是几分钟的事。希望帮到你。
本文还有配套的精品资源,点击获取