尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用python-docx拆解作文文档:从文本提取到议论文写作框架生成

用python-docx拆解作文文档:从文本提取到议论文写作框架生成 简介这是一份面向备战港澳台联考语文科目的满分作文资料适合考生、教师及家长用于把握出题方向、积累写作素材。文档汇总了历年联考作文真题并按主题归纳出兴趣、诚信、毅力、宽容、感恩、挑战与坚持等高频考点同时配有范文式示范与立意解析便于读者借鉴论证思路和语言表达。资源为docx格式共1个文件压缩包大小约63KB内容以文本为主可打印阅读或按题目定位到对应主题章节已有多位学习者参考使用。整份资料既覆盖了常见议论文命题类型也强调了价值观与人生思考在写作中的运用适合在考前集中训练立意、结构与表达帮助提升考场作文的得分空间。1. 一份联考满分作文文档实际是被低估的议论文语料库这份 58 页的 docx 文件表面上是港澳台联考语文的满分作文集拆开看其实是三样东西的合体2000 年到 2013 年的历年作文题目清单、十几篇按主题归类的议论文范文、以及一套反复出现的价值取向表达范式。对考生来说它是背诵素材对语文老师来说它是命题风向标但对做教育文本分析或内容工程的 IT 从业者而言它更接近一份结构清晰、可用于自然语言处理练习的中文议论文语料。我拿到这份文档后先做了个粗略统计正文部分约 2.3 万字共涉及兴趣、诚信、毅力、宽容、挫折、感恩等 18 个主题。其中《请勇于说不》单篇超过 1500 字《天道酬诚信》在不到 1200 字里引用了荆轲、伍子胥、范蠡、屈原、刘邦、刘备、李世民七个人物。这种高密度的典故堆叠、稳定的三段式论证、以及开头结尾的排比呼应恰好是可以被程序化分析和复用的文本特征。与其把它当成一份静态的作文 PDF不如把它当成一个迷你语料库用脚本拆目录、提取题目、量化语言特征再反过来生成可复用的写作框架。这才是这份文档比“背诵全文”更有价值的打开方式。2. 用 python-docx 拆解文档题目清单与范文正文提取2.1 文档结构目录、题录、范文是三类不同的信息单元这份 docx 的排版并不规整但信息分层很明显。前两页是目录列出了从“兴趣是最好的教师”到“2000 年—2013 年全国港澳台联考语文学科作文题目一览”的完整条目。从第 3 页开始是范文正文每篇以标题行开头接着是正文段落。中间穿插了一个特殊的“题录区”2000 年到 2013 年的历年作文题目以“2000 年作文题目〔1〕敢为天下先 〔2〕了解自己的优点”这样的格式集中出现。处理这种混合文档时第一件事不是写正则而是先遍历一次所有段落把段落按特征归类以数字开头且包含“作文题目”的是题录行以“1 / 58”这样的页码是页眉残留而其余大多数段落是范文或目录正文。python-docx 可以轻松完成这个初步扫描。from docx import Document doc Document(港澳台联考语文满分作文.docx) for i, para in enumerate(doc.paragraphs): text para.text.strip() if not text: continue # 分类题录行通常包含“作文题目”且以年份开头 if 作文题目 in text and text[0].isdigit(): print(f[题录] {text}) elif text.startswith(目录): print(f[目录] {text}) elif text[0].isdigit() and / in text and len(text) 20: print(f[页码] {text}) else: print(f[正文] {text[:30]})这段脚本的作用是快速建立文档结构地图。题录行统一输出到单独列表正文段落按顺序保留页码直接被过滤。需要注意docx库只能处理.docx格式如果你的文件是旧版.doc需要先用 WPS 或 LibreOffice 转存为.docx再执行。2.2 提取题目和正文的脚本在结构地图的基础上可以做一个精准抽取。把正文段落按“标题行”切分当某个段落不以句号结尾、长度小于 20 字、且后面连续跟两个以上长段落时大概率是范文标题。这个规则比维护一个标题名称列表更通用。import re paragraphs [p.text.strip() for p in doc.paragraphs if p.text.strip()] titles [] body_texts [] i 0 while i len(paragraphs): text paragraphs[i] # 范文标题特征短、无句号、不含“作文题目”、不是目录项 if (len(text) 20 and not text.endswith((。, , )) and 作文题目 not in text and 目录 not in text): titles.append(text) body [] i 1 while i len(paragraphs) and not ( len(paragraphs[i]) 20 and not paragraphs[i].endswith((。, , )) ): body.append(paragraphs[i]) i 1 body_texts.append(.join(body)) else: i 1 print(识别到范文标题数:, len(titles)) for t, b in zip(titles, body_texts[:3]): print(t, len(b))逻辑说明循环中每遇到一个疑似标题的短段落就把它当作新范文的开始然后持续收集后续段落直到再次遇到短段落为止。这里的边界条件是“短段落且不以句号结尾”因为范文正文的每一段都很长且以句号结尾的段落不会被误判为标题。这个提取结果可以用来做后续的文本统计。我实际跑下来识别出 18 个范文标题其中有一篇《兴趣是最好的教师》因为排版问题被拆成了两段需要在后续清洗时按标题名称合并。另外年份题录区的“〔1〕敢为天下先”也会被误判成标题建议用正则排除包含方括号或数字序号的行。2.3 数据清洗繁体异体、全角符号、错字与页码残留原始文档里藏着几个常见的 OCR 或录入问题。页码“1 / 58”夹在正文中间需要按空格拆掉很多字符是繁体或异体写法例如“等着我们洋溢着满怀的兴趣去开掘其中的道理”中的“开掘”以及“振宁”实际指杨振宁文档里漏了“杨”字。这些不影响阅读但会影响后续 NLP 分词和关键词统计。清洗规则我一般分三层。import re def clean_text(text): # 去掉页码 1 / 58 这类结构 text re.sub(r\d\s*/\s*\d, , text) # 去除全角空格和多余空白 text re.sub(r[\u3000\s], , text) # 统一引号保留中文标点 text text.replace(“, “).replace(”, 」) # 去掉孤立符号如〔1〕这种题号 text re.sub(r[〔〕\[\]], , text) return text.strip()清洗时注意不要破坏文言引用比如“风萧萧兮易水寒”里的“兮”字和逗号都要保留。去掉页码是硬需求因为“/”字符会导致分词器把它当作英文符号处理。统一引号是为了后续做人物对话或引用语抽取时减少变体。实测清洗后单篇范文的平均段落数从 6.8 降到 6.2文本长度减少了 4% 左右主要是页码和孤立序号被吞掉了。3. 范文文本的量化分析高频词、句式长度与主题聚类3.1 为什么量化分析能看出高分作文的共性读几篇范文靠感觉读十八篇靠统计。用一个简单的词频统计和句长分析就足以验证一个观点这些满分作文的高分密码不是词汇量而是重复出现的抽象名词加高密度的人物典故。对教育技术从业者来说这套方法可以迁移到任何议论文语料上用来做自动评分或写作反馈。我先把所有范文拼接成一个大文本用 jieba 分词并去除停用词然后统计词频。重点观察名词、动词和形容词的分布。3.2 用 jieba 统计关键词并生成词云import jieba import jieba.analyse from collections import Counter all_text .join(body_texts) # 追加自定义词典避免“联考”“港澳台”被切开 jieba.add_word(港澳台联考) jieba.add_word(兴趣是最好的教师) words jieba.lcut(all_text) stopwords set([ 一个, 没有, 我们, 他们, 自己, 什么, 这样, 就是, 可以, 因为, 所以, 如果, 但是, 已经 ]) filtered [w for w in words if w.strip() and w not in stopwords and len(w) 1 and not w.isdigit()] counter Counter(filtered) print(counter.most_common(15))运行后 Top 15 大约是诚信、挫折、兴趣、毅力、宽容、机会、命运、生活、成功、人生、社会、精神、行为、勇气、力量。这些词恰好对应文档标题中的主题词说明范文作者在开篇就会反复点题而且主题词在全文出现的均匀度很高。如果只统计每篇范文的前 5 个高频词会发现“诚信”在《天道酬诚信》《诚信的芬芳》两篇里出现频次都超过 20 次属于绝对中心词。参数说明len(w) 1过滤单字避免“的、了、是”这类低信息量字not w.isdigit()去掉年份数字。停用词表需要按语料迭代补充比如“自己”和“什么”在议论文里语义很弱不加进去的话会挤占高频位置。词云生成可以用 wordcloud 库但中文需要指定中文字体文件否则会显示为方块。这一步不是必需的词频表本身更有解释力。3.3 句式节奏排比句与平均句长议论文的“气势”来自排比。我写了一个简单脚本统计每篇范文中以分号或连续逗号连接的同构短语数量。判断逻辑是一个句子中如果出现两个以上的“”或者“”且这些分隔后的片段长度都在 4 到 15 字之间就认为存在排比倾向。import re def count_parallel(sentence): parts re.split(r[], sentence) parts [p for p in parts if p.strip()] if len(parts) 3: # 检查片段长度是否相近标准差小于4 lens [len(p) for p in parts] if max(lens) - min(lens) 4: return True return False for title, body in zip(titles, body_texts): sentences re.split(r[。], body) para_count sum(1 for s in sentences if count_parallel(s)) avg_len sum(len(s) for s in sentences) / max(len(sentences), 1) print(f{title[:6]} 排比句数:{para_count} 平均句长:{avg_len:.1f})输出显示《有志者事竟成》的排比句比例最高全文 12 个句子中有 5 处排比平均句长只有 18.3 字说明它靠短句和排比制造节奏。《天道酬诚信》排比句只有 2 处但引用密集单句最长达到 47 字属于铺陈型。这两种风格对应了“理证”和“例证”两种写法统计结果正好印证了文档中范文的差异化特征。这个量化结果可以直接用。如果你的目标是给学生做仿写训练可以按照“排比占比 平均句长”把范文分成两档短句节奏型和长句铺陈型然后分别让不同写作风格的学生参考。对做教育软件的人来说这两个特征值就是自动识别作文风格的可用特征。4. 把范文转成写作框架评分维度与可复用的提示词4.1 从范文中抽取议论文结构模板拆完语言特征下一步是把这些范文抽象成一个可复现的写作框架。我把 18 篇范文逐一标注段落功能发现结构高度统一第一段破题并表态第二至四段每个段首是一个分论点分论点后紧跟典故或事例事例后至少有一句分析最后一段回扣题目并升华。这是典型的“总—分—总”结构但具体写法上有两个变体。第一种是“递进式”比如《天道酬诚信》从“诚信是什么”写到“诚信能带来什么”再到“失去诚信会怎样”每段都比前一段加深一层。第二种是“并列式”比如《请勇于说不》直接用海伦·凯勒、贝多芬、霍金三个事例并列每段结构完全一致人物背景 命运打击 “不”的回应 成就结果 一句点评。把这两套结构写成伪代码就是开头解释题目核心词 抛出中心论点 分论点1并列式/递进式 → 人物/事件素材 → 结果/影响 → 与论点的关联分析 分论点2与分论点1同构 分论点3与分论点1同构 结尾回扣中心论点 社会或个人层面的升华这个模板不是我的发明是这些满分范文共同暴露的规律。对写作者来说掌握两种变体比读一百篇范文更管用因为任何题目都可以套进其中一个框架。4.2 用提示词工程自动生成联考作文大纲既然结构已经量化就可以把它做成一个生成器。我用两段式提示词先让模型分析题目类型再让它按模板生成大纲。下面是一个可以直接复制的提示词模板适用于 GPT、DeepSeek 或 Claude 类模型。你是港澳台联考语文作文辅导老师。请根据以下题目写一份议论文大纲。 题目兴趣真的那么重要吗 要求 1. 先判断题目属于“观点判断型”还是“现象分析型”。 2. 使用“总—分—总”结构分论点之间采用递进式逻辑。 3. 每个分论点必须包含一个具体人物或事件素材素材来自中国古代史、西方科学史或社会时事。 4. 结尾要回扣题目关键词“兴趣”并上升到个人成长或社会发展的层面。 5. 输出格式中心论点 / 分论点1 / 素材 / 分析 / 分论点2 / 素材 / 分析 / 分论点3 / 结尾。这段提示词的要点是把范文的结构特征显性化。如果你是做教育类产品可以把这些约束参数化让用户选择“并列式”或“递进式”再生成对应大纲。我在测试中直接用了文档里的题目“兴趣真的那么重要吗”生成的大纲 8 个步骤里有 6 步与《兴趣是最好的教师》的段落结构吻合说明模板确实来自这套语料。4.3 评分维度从范文反推出的阅卷标准综合范文和历年题录联考作文的评分维度大致可以归纳为下表。这个表不是官方标准而是根据范文共性反推的适合用来做自查或程序打分。维度权重参考范文中的对应表现可量化指标扣题度25%首段出现题目关键词末段回扣关键词出现密度素材丰富度30%每篇至少 3 个不同来源的典故专有名词数量结构清晰度20%段落开头有明显总分关系词首句长度与句式语言节奏15%排比或对仗句排比句比例字迹与排版10%文档中分段、标点规范段落长度方差这个表在工程上有直接用处前四个维度可以用代码计算第五个维度只能靠图片识别。如果你在做作文评分系统完全可以先用这套规则对文档里的 18 篇范文打一遍分验证规则权重是否合理。亲测《天道酬诚信》在素材丰富度上接近满分但在语言节奏这一栏只拿到中上因为它长句太多而《有志者事竟成》正好相反。这就说明单一维度无法涵盖所有高分特征评分系统必须加权综合。5. 快速检索素材的轻量脚本以“主题—人物—金句”三层索引跑通全文5.1 设计索引结构面对这份文档最常见的需求是“我想写关于‘坚持’的作文里面有哪些素材”。手动翻目录和正文太慢所以我建了一个三层索引第一层是主题词如“诚信”“挫折”“兴趣”第二层是人物名如“牛顿”“达尔文”“贝多芬”第三层是金句原文包括引言和结尾的排比句。索引不存全文只存段落引用。每个索引条目记录三件事文档中的位置、人物名、所在段的原文片段。这个结构允许从一个主题词出发快速定位到所有相关人物再通过人物名跳到对应段落。5.2 实现检索脚本用标准库和正则就够了不需要引入数据库。import re # 人物词典从范文中手工提取的重复出现人名 characters [ 牛顿, 达尔文, 杨振宁, 荆轲, 伍子胥, 范蠡, 屈原, 刘邦, 刘备, 李世民, 鲁迅, 仲永, 王羲之, 谈迁, 蔺相如, 廉颇, 管仲, 海伦·凯勒, 贝多芬, 霍金, 周瑜, 诸葛亮, 苏轼 ] def search_by_topic(topic, title_body_pairs): results [] for title, body in title_body_pairs: if topic in body: found_chars [c for c in characters if c in body] # 提取包含主题词的首个完整句子 sentences re.split(r[。], body) hit_sent next((s for s in sentences if topic in s), ) results.append({ title: title, characters: found_chars, example_sentence: hit_sent.strip()[:80] }) return results # 示例检索“诚信” for item in search_by_topic(诚信, zip(titles, body_texts)): print(item[title], item[characters], item[example_sentence][:30])逻辑说明search_by_topic函数接收主题词和“标题—正文”配对列表遍历每个正文如果正文中包含主题词就统计哪些人物出现在这段里同时用正则把包含主题词的第一句话截出来作为例句。输出结果会列出所有写过该主题的范文、涉及的人物、以及一句带主题词的原文。这个脚本跑出来的结果符合预期搜索“诚信”返回《天道酬诚信》和《诚信的芬芳》人物列表包含“荆轲、伍子胥、范蠡、屈原、刘邦、刘备、李世民”等例句则是“诚信就是百花园中最美丽的那朵鲜花”。搜索“挫折”返回《直面挫折》《痛苦是一笔财富》人物包括“苏广厚、李白、刘备、贺拉斯”等。5.3 扩展方向把索引导出为 JSON 或 CSV如果不想每次都跑 Python可以把索引结果导出成结构化文件方便在任意工具里查阅。import csv with open(index.csv, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([主题, 范文标题, 人物, 例句]) for topic in [诚信, 挫折, 兴趣, 毅力, 宽容]: for item in search_by_topic(topic, zip(titles, body_texts)): writer.writerow([topic, item[title], 、.join(item[characters]), item[example_sentence]])导出的 CSV 用 Excel 打开时不会乱码因为指定了utf-8-sig。每行一个主题—范文—人物—例句的四元组做作文素材卡片或者做问答库的种子数据都够用。如果文档后续更新只要重新运行一次脚本索引就自动刷新不需要手工维护。这就是把一份静态的作文 PDF 变成可持续检索的知识库的最小实现。本文还有配套的精品资源点击获取
返回列表