新视野大学英语听力原文PDF提取与精听训练包构建

发布时间:2026/10/11 20:24:52
新视野大学英语听力原文PDF提取与精听训练包构建
简介这份《新视野大学英语(第三版)视听说教程2听力原文.pdf》面向使用该教材的高校学生及英语自学者用于解决视听说练习中听力材料难以核对、课堂跟读缺乏文本参照的问题。资源为单一PDF文档压缩包约320KB内容完整收录Unit 1等单元的听力脚本涵盖Sharing、Listening等板块的对话与独白原文并标注说话人角色便于对照音频逐句精听、整理生词与句型。脚本围绕“Life is a learning curve”展开涉及西班牙语、法语、阿拉伯语等多语种学习经历以及吉他、绘画、网站设计等技能习得话题同时包含“Ask the Expert”栏目中关于语言学习障碍与方法的讨论可作为口语模仿、听写训练和话题拓展的文本依据。目前已有2523人学习下载适合需要反复精听、核对原文或备考视听说课程的学习者使用。1. 一份听力原文 PDF 为什么值得当成数据资产来做带过视听说课的老师大概都遇到过这种场面学生课下想精听手里只有音频听不清的地方反复倒带十分钟过去还在同一句话上打转老师想备课做课件得一句一句把音频敲成文字一个单元下来眼睛都花了。新视野大学英语(第三版)视听说教程2听力原文.pdf 这类材料本质上就是把音频里的对话、短文、练习指令全部转成可检索、可复制、可二次加工的文字。它解决的不是有没有音频的问题而是音频里的信息能不能被快速定位、拆解、重组的问题。适合谁用一是想把听力材料做成精听训练包的老师二是想拿原文做语料分析、做字幕对齐、做题库的技术型教研人员三是想批量处理同类教材原文的开发者。这一章先把这份 PDF 的定位讲清楚后面几章再落到怎么提取、怎么清洗、怎么用。2. 从 PDF 到可用文本提取链路怎么搭才不返工2.1 先判断这份 PDF 是真文本还是扫描图拿到一份听力原文 PDF第一件事不是急着写代码而是判断它的底层结构。用文本编辑器直接打开如果能选中文字、复制出来不乱码说明是电子排版生成的真文本 PDF如果整页只能框选出一个大对象、复制出来是空白或乱码那大概率是扫描件或图片封装。这两种情况的处理链路完全不同判断错了后面全白干。判断方法很简单用 Python 的 pdfplumber 抽一页看看import pdfplumber # 打开 PDF抽取第 5 页的文字 with pdfplumber.open(listening_text.pdf) as pdf: page pdf.pages[4] # 索引从 0 开始 text page.extract_text() # 如果 text 为 None 或长度极短基本可判定为扫描件 print(repr(text[:200]) if text else NO TEXT LAYER)如果输出是NO TEXT LAYER或者只有零星几个字符说明没有文本层需要走 OCR 路线如果能正常输出成段英文说明可以直接抽取。这一步花两分钟能省掉后面几小时的返工。2.2 真文本 PDF 的抽取pdfplumber 与版面参数确认有文本层之后抽取本身不难难的是保住版面顺序。听力原文 PDF 常见双栏排版直接extract_text()会把左右栏串在一起读起来前言不搭后语。这时候要用到版面裁剪参数。import pdfplumber with pdfplumber.open(listening_text.pdf) as pdf: page pdf.pages[4] # 按左右半页分别裁剪避免双栏串行 left page.crop((0, 0, page.width / 2, page.height)) right page.crop((page.width / 2, 0, page.width, page.height)) left_text left.extract_text() or right_text right.extract_text() or # 先左后右拼接符合阅读顺序 full_text left_text \n right_text print(full_text[:300])crop的四个参数是(x0, y0, x1, y1)单位是点pointpage.width和page.height是当前页尺寸。双栏材料一般从页面中线切如果栏间距不对称可以先打印page.width看看实际宽度再调。extract_text()返回None的情况要兜底成空字符串否则拼接时会报类型错误。2.3 扫描件的 OCR 路线分辨率与语言包两个关键参数如果确认是扫描件就得走 OCR。常见做法是先用 pdf2image 把每页转成图片再用 Tesseract 识别。这里有两个参数直接决定成败DPI 和语言包。# 把 PDF 每页转成 300 DPI 的 PNG pdftoppm -r 300 -png listening_text.pdf page # 用英文语言包识别输出到 out 目录 tesseract page-05.png out/page-05 -l eng --psm 6-r 300是分辨率低于 200 识别率会明显下降高于 400 收益递减还拖慢速度300 是常用平衡点。-l eng指定英文语言包听力原文里如果混有中文指令可以改成-l engchi_sim。--psm 6表示假定是一整块统一文本适合正文段落如果是分栏或带表格试试--psm 4或--psm 3让 Tesseract 自动分析版面。OCR 出来的文本一定会有错字尤其是l和1、rn和m这类后面清洗环节要专门处理。2.4 清洗把能看变成能用抽取出来的原始文本通常带着页眉、页脚、页码、多余空行。听力原文还有一个特殊问题说话人标记如W:M:Conversation 1和正文混在一起需要结构化。import re def clean_listening_text(raw: str) - list: lines raw.split(\n) cleaned [] for line in lines: line line.strip() # 跳过纯页码行和空行 if not line or re.fullmatch(r\d, line): continue # 跳过常见页眉页脚关键词 if re.search(r(Unit|Contents|Listening|Speaking), line, re.I) and len(line) 20: continue # 修正常见 OCR 错误 line line.replace(1t, it).replace(0f, of) cleaned.append(line) return cleaned with open(raw.txt, encodingutf-8) as f: result clean_listening_text(f.read()) print(\n.join(result[:20]))这段逻辑做了三件事去空行和纯数字页码、按长度和关键词过滤页眉页脚、替换高频 OCR 错字。re.fullmatch(r\d, line)只匹配整行都是数字的情况不会误伤正文里的数字。页眉过滤用关键词 长度小于 20双条件避免把正文里正常出现的listening单词误删。清洗规则要根据实际输出反复调没有一劳永逸的版本。3. 把原文变成精听训练包切分、对齐与导出3.1 按说话人和场景切分对话听力原文的价值在于可定位。一段对话里谁说了什么如果能结构化就能做角色扮演、做填空、做逐句复读。切分的依据是说话人标记常见格式有W:M:Man:Woman:几种。import re def split_dialogue(lines: list) - list: turns [] current {speaker: None, text: } # 匹配 W: / M: / Man: / Woman: 开头的行 speaker_pat re.compile(r^(W|M|Man|Woman)\s*[:]\s*(.*)$, re.I) for line in lines: m speaker_pat.match(line) if m: # 遇到新说话人先把上一轮存起来 if current[speaker]: turns.append(current) current {speaker: m.group(1).upper(), text: m.group(2)} else: # 续行拼到当前说话人后面 current[text] line if current[speaker]: turns.append(current) return turns turns split_dialogue(result) for t in turns[:5]: print(t[speaker], -, t[text][:60])核心思路是遇到新标记就收口上一轮。speaker_pat用re.I忽略大小写兼容w:和W:。续行拼接用空格而不是换行方便后续按句处理。如果原文用的是Speaker 1这种格式把正则改成^(Speaker\s*\d)\s*[:]\s*(.*)$即可。切分完建议人工抽查前 20 轮确认没有把正文里的冒号误判成说话人。3.2 句子级切分与时间轴预留要做逐句复读就得把每轮对话再切成句子并且给每句留一个时间戳字段。时间戳如果 PDF 里没有可以留空后续用音频对齐工具补但字段结构要先定好不然后面加字段要重跑全流程。import re def split_sentences(turns: list) - list: sentences [] for t in turns: # 按句号、问号、感叹号切分保留标点 parts re.split(r(?[.?!])\s, t[text]) for p in parts: p p.strip() if len(p) 2: continue sentences.append({ speaker: t[speaker], text: p, start: None, # 预留时间戳 end: None }) return sentences sentences split_sentences(turns) print(len(sentences), sentences) print(sentences[0])re.split(r(?[.?!])\s, ...)是零宽断言在标点之后、空白之前切标点本身保留在句尾。len(p) 2过滤掉切分产生的碎片。start和end先置None等音频对齐时再填。这个结构导出成 JSON 或 CSV 都方便JSON 保结构CSV 方便用 Excel 打开检查。3.3 导出格式选择JSON、CSV 与 SRT 的取舍不同用途导出不同格式。做语料分析用 JSON做表格检查用 CSV做字幕用 SRT。三种格式的字段映射关系如下格式适用场景关键字段注意事项JSON程序处理、嵌套结构speaker, text, start, end保留完整层级体积较大CSV人工校对、Excel 查看同上扁平化文本含逗号需加引号转义SRT视频字幕、播放器加载序号, 时间轴, 文本时间轴格式为00:00:01,000导出 CSV 时用 Python 的 csv 模块自动处理转义不要手动拼字符串import csv with open(sentences.csv, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[speaker, text, start, end]) writer.writeheader() writer.writerows(sentences)encodingutf-8-sig带 BOMExcel 打开中文不乱码newline防止 Windows 下多出空行。这两个参数是血泪经验少了任何一个打开文件就是一堆乱码或空行。4. 避坑与排查处理听力原文 PDF 最容易翻车的五个点4.1 双栏串行读出来像两个人同时说话现象抽取的文本里左栏第一句和右栏第一句交替出现读起来逻辑断裂。原因extract_text()默认按页面坐标从上到下、从左到右扫描双栏排版下会把同一水平线的左右两栏拼在一起。解决用page.crop()按栏切分后分别抽取再按先左后右拼接。如果栏宽不对称先打印page.width和每行的x0坐标找到栏间距的中线位置再切。4.2 OCR 把 l 认成 1整句意思全变现象Ill变成I11feel变成fee1查词查不到学生看了更迷糊。原因Tesseract 在无衬线字体下对l和1的区分度低尤其是字号小、分辨率不足时。解决一是提高 DPI 到 300 以上二是清洗阶段做定向替换把1前后是字母的情况替换回l三是关键段落人工校对。定向替换的正则re.sub(r(?[A-Za-z])1(?[A-Za-z]), l, text)只替换夹在字母中间的1不误伤数字。4.3 说话人标记格式不统一切分漏掉一半现象切分出来的对话轮数明显偏少很多内容堆在一个说话人名下。原因原文里W:和Woman:混用或者有的地方用全角冒号正则只匹配了一种。解决正则里用(W|M|Man|Woman)覆盖多种写法冒号用[:]同时匹配半角和全角加re.I忽略大小写。切分后打印轮数和前几轮内容人工确认没有大面积堆积。4.4 页码和页眉混进正文导出后全是噪音现象导出的 CSV 里每隔几十行就出现一个孤零零的数字或Unit 3。原因PDF 每页都有页码和页眉抽取时一并带出来了。解决清洗阶段按行过滤纯数字行直接丢短行且含Unit、Contents等关键词的也丢。注意过滤条件要加长度限制否则正文里正常出现的Unit单词会被误删。4.5 编码不统一中文指令变问号现象原文里混排的中文指令如听录音填空导出后变成???。原因读取或写入时用了gbk或默认编码和文件实际编码不匹配。解决全程统一用utf-8读写写 CSV 时用utf-8-sig兼容 Excel。如果原始文件是gbk读取时显式指定encodinggbk转成utf-8再处理。5. 进阶用原文做语料分析的一个具体技巧原文清洗干净之后除了做精听包还能做一件更有意思的事统计高频词和短语反推这套教材的词汇难度分布。这个技巧对教研人员特别实用能快速判断某个单元的生词密度是否适合当前学生水平。具体做法是先用nltk或spaCy做词形还原再统计词频最后和通用词表对比找出超出基础词表的词。下面是一个最小可跑的例子import re from collections import Counter # 假设 sentences 是前面切分好的句子列表 all_text .join(s[text] for s in sentences) # 只保留字母和空格转小写 words re.findall(r[A-Za-z], all_text.lower()) # 简单停用词表实际项目可换成完整版 stopwords {the, a, an, is, are, was, were, to, of, and, in, it, i, you, he, she} content_words [w for w in words if w not in stopwords and len(w) 2] freq Counter(content_words) for word, count in freq.most_common(20): print(f{word}: {count})这段代码做了四步拼接所有句子、正则提取纯字母词、去停用词和短词、统计词频。re.findall(r[A-Za-z], ...)保留撇号这样dont不会被切成don和t。停用词表这里只列了一小部分实际用的时候建议换成完整的英文停用词表否则the、is这类会占满前几名看不出真正的主题词。拿到词频之后可以进一步做两件事。一是按单元分组统计看每个单元的主题词是否和单元标题吻合如果某个单元高频词全是the、is说明原文抽取质量有问题需要回头检查。二是和基础词表比如常见的前 2000 高频词做差集差集里的词就是这套材料的超纲词可以整理成生词表发给学生。我自己的习惯是每次处理完一份新的听力原文先跑一遍词频用前 20 个词快速判断这份材料干不干净。如果前 20 个词里出现了明显的 OCR 错字比如1t、0f说明清洗规则还有漏洞得回去补。这个习惯帮我省了很多次返工——与其等学生反馈这个词查不到不如在导出前就用词频把噪音揪出来。另外词频统计的结果建议存成 CSV按单元分文件方便后续对比不同版本教材的难度变化。还有一个细节值得注意听力原文里的口语化表达gonna、wanna、kinda在标准词表里查不到但它们是听力理解的重点。可以在词频统计之后单独用一个口语缩略词表去匹配把这些词标出来做成口语表达专项。这一步不需要复杂代码一个字典加一次遍历就能完成但对教学的价值很高——学生往往就是卡在这些缩略形式上。希望帮到你。本文还有配套的精品资源点击获取