资讯动态

SMOG公式工程化实战:Python实现英文文本可读性评分

发布时间:2026/10/17 9:35:01 来源:尧图企业网站定制
简介smog-formula 是一份基于 1969 年 SMOGGobbledygook 简单度量公式实现文本阅读难易程度检测的 JavaScript 工具包面向需要评估文章可读性等级的前端开发者、内容编辑与教育技术研究者。它通过统计句子数与多音节词数量快速换算出对应的阅读年级水平适用于稿件分级、教材难度评估等场景。资源包共 12 个文件以 js 源码与 json 配置为主辅以 yml 工作流、md 说明文档及 license 等工程文件压缩后仅约 6KB体积轻量、便于直接引入项目。该包仅支持 ESM需 Node 12 环境并以 import 方式加载核心导出 smogFormula 方法传入句子数与多音节词数即可得到难度数值。目前已有 368 人学习下载读者可借此掌握 SMOG 公式的工程化实现思路并直接复用于文本可读性检测功能开发。1. 把 SMOG 公式装进文本流水线1969 年的老指标为什么还在被调用做内容风控、教育测评或者无障碍改造的团队几乎都会遇到同一个需求给一段文本打一个「读起来费不费劲」的分。很多人第一反应是上大模型打分但真到要写进 CI、要能复现、要能跟业务方解释「为什么这篇被判难」的时候往往还是回到几个经典可读性公式上SMOG 就是其中最常被点名的一个。它的全称是 Simple Measure of Gobbledygook1969 年提出核心思路朴素到有点反直觉不数词长、不查词表只数多音节词和句子数就能估出读者需要读到几年级才读得懂。标题里的 smog-formula 指的就是把这套公式工程化——输入一段文本输出一个 SMOG 指数和对应的年级门槛。它适合谁适合要把可读性做成可量化、可回归、可写进验收标准的人而不是只想看个热闹的人。2. SMOG 公式到底在算什么多音节词与句子的比值逻辑2.1 公式的原始形态与三个变量SMOG 的经典形式是这样的先取若干句子作为样本统计其中「多音节词」的数量也就是音节数大于等于 3 的词然后套公式SMOG 1.0430 × √(多音节词数 × (30 / 句子数)) 3.1291这个 1.0430 和 3.1291 是原作者在 1969 年用回归拟合出来的常数不是拍脑袋。公式里最关键的变量只有一个多音节词密度。句子数出现在分母里作用是做归一化——你统计了 30 个句子还是 10 个句子多音节词数要按比例折算到「每 30 句」这个基准上再开方。开方这一步是很多人第一次看会愣住的地方它意味着多音节词翻 4 倍SMOG 只涨大约 1 倍指标对长词的敏感度是递减的。理解这一点后面调阈值和解释分数才不会翻车。为什么是「多音节」而不是「长单词」因为英文里音节数和字母数并不严格对应interesting四个音节但只有 11 个字母through7 个字母却只有 1 个音节。SMOG 选择音节是为了更贴近「读者要在脑子里拆几次发音」这个认知负担。这也是它比单纯数字符的公式更抗玄学的地方。2.2 为什么工程上更常用「简化版」原始公式要求你固定采样 30 个句子这在批量处理里很别扭。工程上更常见的是它的等价变形直接对整篇文本算SMOG 1.0430 × √(多音节词总数 × 30 / 句子总数) 3.1291这样你不需要截取样本整篇丢进去就能出分。代价是文本太短时比如只有两三句开方前的数值波动极大分数会飘。所以我在实现里一般会加一个最小句子数门槛低于门槛直接返回「样本不足」而不是硬给一个看起来精确的假分数。这个门槛设多少经验值是 10 句低于 10 句的文本SMOG 的置信度不值得你写进报告。2.3 音节计数整个方案里最容易出错的一环SMOG 的准确性几乎完全押在音节计数上。英文音节计数没有完美规则常见做法是「元音组计数法」把连续的元音字母算作一个音节再处理词尾不发音的 e。这套规则对大多数常用词够用但遇到专有名词、缩写、连字符词就会翻车。比如API按字母读是三个音节按元音组规则可能算成一个state-of-the-art这种连字符词你得先决定拆不拆。我的做法是先做一轮预处理把连字符词拆开分别计数把全大写缩写按字母数近似成音节数剩下的走元音组规则。这一步不做SMOG 分数会系统性偏低因为缩写词被当成单音节词漏掉了。3. 用 Python 把 smog-formula 跑起来从分词到出分的完整链路3.1 最小可运行实现下面这段代码不依赖任何重型 NLP 库只用标准库加一个正则目的是让你能直接复制进项目里跑通再按需替换音节计数器。import re import math VOWELS aeiouy def count_syllables(word: str) - int: 元音组音节计数处理词尾不发音 e 和常见缩写 word word.lower().strip() if not word: return 0 # 全大写缩写按字母数近似调用前需保留原始大小写信息 # 这里简化处理长度4 且无元音的词按字母数算 if not any(ch in VOWELS for ch in word): return max(1, len(word)) # 去掉词尾不发音的 e但保留 le 结尾如 table if word.endswith(e) and not word.endswith(le): word word[:-1] # 连续元音算一组 groups re.findall(r[aeiouy], word) return max(1, len(groups)) def split_sentences(text: str): 按 . ! ? 切句过滤空句 parts re.split(r[.!?], text) return [p.strip() for p in parts if p.strip()] def smog_index(text: str, min_sentences: int 10): sentences split_sentences(text) if len(sentences) min_sentences: return {smog: None, grade: None, reason: 样本不足} words re.findall(r[A-Za-z][A-Za-z\-]*, text) poly 0 for w in words: # 连字符词拆开分别计数 subs w.split(-) syl sum(count_syllables(s) for s in subs) if syl 3: poly 1 smog 1.0430 * math.sqrt(poly * 30.0 / len(sentences)) 3.1291 return { smog: round(smog, 2), grade: round(smog), # 对应年级门槛 poly_words: poly, sentences: len(sentences), words: len(words), } if __name__ __main__: sample ( The implementation demonstrates considerable flexibility. However, configuration complexity increases operational overhead. Teams should evaluate maintainability before adoption. Documentation quality determines onboarding efficiency. Performance characteristics vary across deployment environments. Monitoring infrastructure requires additional investment. Security considerations mandate regular auditing procedures. Scalability depends on architectural decisions made early. Testing coverage influences long-term reliability significantly. Migration strategies should account for data integrity requirements. ) print(smog_index(sample))跑出来你会看到一个 SMOG 在 15 上下的分数对应大学高年级阅读门槛。这段代码的关键点有三个count_syllables里对词尾 e 的处理决定了分数不会虚高split_sentences用正则切句遇到Mr.这类缩写会误切生产环境要加缩写白名单smog_index里的min_sentences是防止短文本给出假精确的保险丝。3.2 参数怎么调三个你一定会碰到的旋钮第一个旋钮是min_sentences。默认 10 是我在内容审核场景下的取值因为审核文本通常成段。如果你做的是标题或短摘要可读性这个门槛要降到 3 到 5同时接受分数波动变大或者改用其他更适合短文本的指标配合判断。第二个旋钮是音节计数策略。上面用的是元音组规则够快但不够准。如果你对准确度要求高可以引入一个音节词典做查表查不到再回退到规则。代价是词典体积和加载时间取舍看你是在线服务还是离线批处理。第三个旋钮是「多音节词」的判定边界。严格按音节数 ≥ 3 是最标准的做法但有些团队会把专有名词、代码标识符排除在外因为读者对Kubernetes这种词的认知负担和普通长词不一样。这个调整会让分数更贴近真实阅读体验但会让你的 SMOG 不再能和别人的分数直接对比。我的建议是对外报告用标准口径对内优化用调整口径两套分开存。3.3 把分数映射到可执行的结论SMOG 分数本身是个数字业务方要的是「这篇能不能发」。常见的映射是SMOG 小于 8 对应初中以下8 到 12 对应高中13 到 16 对应大学17 以上对应研究生。这个映射不是公式自带的是行业惯例你在写验收标准时要明确写清楚用的是哪套映射否则评审时一定有人拿另一个口径来跟你对线。我一般会在返回结构里同时给原始分和年级让下游自己决定怎么用。4. 避坑与排查SMOG 落地时最常翻车的五件事4.1 短文本给出假精确分数现象一段三句话的产品描述SMOG 算出 14.7业务方拿去当硬指标卡人。原因句子数太少公式里30 / 句子数这一项被放大多音节词数稍微动一下分数就跳。解决设最小句子数门槛低于门槛返回「样本不足」或者改用句子数不敏感的指标。别让一个统计上不可靠的数字进决策链。4.2 音节计数把缩写词算漏现象一篇满是API、SDK、HTTP的技术文档SMOG 分数低得离谱看起来像儿童读物。原因元音组规则把这些无元音或单元音的缩写算成 1 个音节而读者实际是按字母逐个读的。解决预处理阶段识别全大写缩写按字母数近似音节数或者维护一个缩写白名单单独处理。4.3 句子切分被缩写和小数点带偏现象文本里出现e.g.、3.14、U.S.切句后句子数虚高SMOG 被拉低。原因正则按.切句没有排除非句末的点。解决切句前先保护常见缩写和小数点或者用更保守的切分规则——只在「点 空格 大写字母」处切。这个坑在技术文档里出现频率极高。4.4 把 SMOG 当成唯一可读性判据现象团队用 SMOG 一个指标决定内容能不能上线结果把很多正常的技术内容误杀。原因SMOG 只反映多音节词密度不反映句子结构复杂度、术语熟悉度、上下文依赖。解决SMOG 作为初筛配合人工抽检或第二个指标交叉验证。单一指标做硬门槛迟早会有人拿着反例来找你。4.5 版本和口径不统一导致分数对不上现象两个团队用同一个 smog-formula同一段文本算出两个分数互相质疑对方实现有问题。原因一个用了原始 30 句采样版一个用了整篇简化版或者一个把连字符词拆开一个没拆。解决把口径写进接口文档——用哪个公式变体、音节计数规则、最小句子数、连字符处理方式全部固定下来最好写进单元测试的期望值里。5. 让 SMOG 真正可用的两个进阶技巧第一个技巧是给 SMOG 加一个「多音节词清单」输出。分数只能告诉你「难」清单能告诉你「难在哪」。我在实现里会额外返回被判定为多音节词的词频排序业务方拿到之后能直接定位到具体是哪些词在拉高分数改起来有的放矢。这个改动成本很低但对内容团队的可用性提升很大——他们不需要理解公式只需要知道「把这三个词换掉分数能降一档」。第二个技巧是用回归测试锁住行为。SMOG 实现里任何一个预处理改动都可能让全量分数漂移所以我会准备一组固定文本和期望分数每次改音节计数或切句逻辑就跑一遍。下面是一个 pytest 风格的骨架import pytest from smog import smog_index CASES [ # (文本, 期望 SMOG 分数, 容差) (Short text here., None, 0), # 样本不足应为 None (The cat sat on the mat. * 12, 3.5, 0.5), # 全单音节词分数应很低 ] pytest.mark.parametrize(text,expected,tol, CASES) def test_smog_stable(text, expected, tol): result smog_index(text) if expected is None: assert result[smog] is None else: assert abs(result[smog] - expected) tol这个骨架的价值不在断言本身而在于它逼你把「期望行为」写下来。我见过太多团队 SMOG 实现改了三版没人说得清第一版和第二版分数差在哪最后只能全部重算。有了回归用例改动的影响面一目了然。还有一个容易被忽略的点SMOG 对语言是强绑定的。它的常数和音节规则都是为英文设计的直接套到中文或其他语言上没有任何意义。如果你的场景是多语言SMOG 只能覆盖英文部分其他语言要么找对应语言的本地化可读性指标要么老老实实做人工评估。我早期在一个多语言内容项目里偷懒把 SMOG 硬套到非英文文本上结果分数完全没有区分度白白浪费了两周排查时间。这个教训让我后来养成了一个习惯任何可读性指标上线前先拿目标语言的正负样本各跑一遍看分数能不能把「明显难」和「明显易」分开分不开就别用。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑