
简介全国大学生英语竞赛本科组的核心词汇复习资料面向参赛考生与英语学习者聚焦竞赛中的高频词条帮助考生系统扩充词汇量、强化语言理解力为阅读理解、听力、写作与口语等环节打下扎实基础。资源采用PDF格式共1个文件压缩包约199KB内容按字母顺序从A至C编排收录abbreviation、abide、abolish、abstract、ambiguous、ample、amplitude等大量竞赛高频词汇结构简洁便于按序记忆与检索。词表不只列出中文释义还兼顾不同语境下的用法差异例如accessory既可表示附件也可指同谋acknowledge表示承认收到或认可努力adoption既指领养孩子也指采纳新策略administration则可指行政机构或政策执行这类细化有助于考生理解词汇的灵活应用。目前已有3183人学习浏览。通过系统记忆并结合阅读、写作与对话练习可有效提升词汇运用能力增强竞赛应试表现与整体英语水平。1. 为什么我需要一份“全国大学生英语竞赛本科”词汇 PDF备赛全国大学生英语竞赛NECCS时最尴尬的不是题做不完而是背词APP里那套词表跟竞赛考纲根本对不上。四六级词表偏通用考研词表偏学术竞赛里却总冒出一些“熟悉又陌生”的搭配义和熟词僻义。所以一份按本科组大纲整理的“全国大学生英语竞赛本科词汇 PDF”就成了很多人桌面上最该常驻的文件——它要能离线查、能打印、能按字母跳转最好还能被脚本拆成 JSON 喂给 Anki。这篇博文就讲我这些年处理竞赛词汇 PDF 的完整套路从抓词表、提取清洗、重新排版到生成卡片和验证覆盖率。全程用 Python命令可直接抄适合竞赛备考生也适合帮学生做词表的老师。2. 用 Python 从公开词表构建“全国大学生英语竞赛本科”词汇库2.1 词表从哪来别手工复制先找“词条服务”而不是网页我要先纠正一个常见误区很多人拿到竞赛官方样题或词汇书想靠复制网页里的词表做成 PDF。但你看到的“单词 音标 释义”在网页 DOM 里往往被打散成多个span复制出来全是换行和空格。更靠谱的来源是竞赛官网或教育考试机构发布的“词汇表附录”通常是一个 XLSX 或 CSV 下载链接。我会先打开开发者工具切到 Network 面板刷新下载页过滤xlsx、csv、json找到真实的资源地址。不要对着网页右键另存因为那通常只是 HTML。如果只有网页版词表那就写爬虫抓接口。我一般先看页面是静态渲染还是 JS 渲染静态的用requests BeautifulSoup动态的在 XHR 里找 JSON 接口。注意动态页面里经常有分页参数page和pageSize每次请求返回少量数据必须循环抓取。2.2 写一个最小抓取脚本把词条存成 CSV下面是一个针对静态词表页的抓取模板目标是把每条词根记录里的“单词、音标、词性、中文释义、频次”抽出来import requests from bs4 import BeautifulSoup import csv import time url https://example.edu.cn/neccl/vocabulary headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://example.edu.cn/neccl/ } resp requests.get(url, headersheaders, timeout10) resp.encoding utf-8 soup BeautifulSoup(resp.text, html.parser) rows soup.select(ul.vocab-list li) data [] for row in rows: word row.select_one(.word).text.strip() phonetic row.select_one(.phonetic).text.strip() pos row.select_one(.pos).text.strip() cn row.select_one(.cn).text.strip() freq row.get(data-freq, 0) data.append([word, phonetic, pos, cn, freq]) with open(neccl_vocab.csv, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([word, phonetic, pos, cn, freq]) writer.writerows(data)这段代码里最值得说的是utf-8-sig编码。用utf-8写 CSV用 Excel 打开时中文会乱码因为 Excel 默认按 GBK 解码utf-8-sig会写入 BOM 头Excel 能自动识别。另外row.get(data-freq)是拿li标签上的自定义属性很多词表服务会把词频或星级放在这里比解析文本更可靠。2.3 请求参数和限速不要一上来就并发抓取时不要用concurrent.futures一次开 50 个线程。竞赛官网的抗并发能力很弱我遇到过抓 200 个词就把我 IP 封了 10 分钟的情况。稳妥的设置是单线程 每请求间隔 1.2 秒并带timeout10。如果页面里有分页我会把页码拼成参数再做循环for page in range(1, 20): params {page: page, pageSize: 100} resp requests.get(url, paramsparams, headersheaders, timeout10) # 解析当前页... time.sleep(1.2)这里pageSize不要贪大很多接口的最大值只有 100你填 500 它也不会报错但会返回空。失败时先看resp.status_code403 是封 IP429 是限速200 但内容为空是参数名不对。3. 用 pdfplumber 提取现有 PDF 里的词条并清洗成 JSON3.1 PDF 里没有“表格”只有坐标和字符很多时候你手里已经有一份排版精美的“全国大学生英语竞赛本科”词汇 PDF但没有原始词表。这时需要提取但绝不能直接pdftotext一把梭因为竞赛词汇 PDF 大多是双栏或三栏混排提取结果会变成一行里同时出现左栏和右栏的词。我推荐用pdfplumber它能把每个字符的坐标和字体信息都暴露出来让我按位置重建词条。先装依赖pip install pdfplumber3.2 按单词的“起始 X 坐标”切割双栏 PDF双栏排版通常有一个规律左栏的单词 X 坐标集中在 50~270pt右栏在 320~540pt。我先读一整页的单词字符按 X 坐标分簇再按 Y 坐标从上到下组合成两列。下面这段代码适用于“每行一个词条、左词典、右释义”的排版import pdfplumber import json def extract_two_columns(pdf_path, page_num): words [] with pdfplumber.open(pdf_path) as pdf: page pdf.pages[page_num] chars page.chars # 取出所有字母和数字字符忽略音标符号 filtered [c for c in chars if c[text].isalpha() or c[text].isdigit()] # 按 X 坐标聚类 cols {} for c in filtered: x_key left if c[x0] 280 else right cols.setdefault(x_key, []).append(c) for col_name, col_chars in cols.items(): # 按 Y 坐标从上到下排序 col_chars.sort(keylambda c: c[top]) line_words [] current_top None for c in col_chars: if current_top is None or abs(c[top] - current_top) 3: line_words.append(c[text]) else: if line_words: words.append(.join(line_words)) line_words [c[text]] current_top c[top] if line_words: words.append(.join(line_words)) return words这个脚本的核心是“行合并阈值”。字符的top坐标相差 3pt 以内我就认为是同一行。但要注意音标字符如ˈ、ˌ不属于isalpha()会被过滤掉所以如果音标混在单词行里提取出来的词条会缺音标。要保留音标得把过滤条件放宽到unicodedata.category(c[text]) ! So但这需要另外写字体判断逻辑。我不建议在这个阶段强求音标先把单词和释义分出来音标后面用在线词典补。3.3 清洗去重、合并换行、修正连字符断词PDF 提取后最常见的三个脏数据问题词条里混入页脚页眉、英文单词被连字符断行、释义里夹着前一个单词的尾巴。我通常用一个清洗函数处理import re def clean_entry(text): # 去掉页脚数字和页眉 text re.sub(r^\d$, , text) # 合并连字符断词competi-\ntion - competition text re.sub(r-\s*\n\s*, , text) # 去掉多余空格 text re.sub(r\s, , text).strip() # 过滤掉纯符号行 if not re.search(r[a-zA-Z], text): return None return text连字符断词要小心有些词本身带连字符比如well-known。我这里只处理“行尾连字符后紧跟换行”的情况正则写成-\s*\n\s*这样well-known没换行就不会被合并。写完之后把所有提取结果存成 JSONall_words [] for page_num in range(0, 180): words extract_two_columns(neccl.pdf, page_num) for w in words: cleaned clean_entry(w) if cleaned: all_words.append(cleaned) unique_words sorted(set(all_words), keystr.lower) with open(neccl_words.json, w, encodingutf-8) as f: json.dump(unique_words, f, ensure_asciiFalse, indent2)set去重时保留第一个出现的顺序我这里直接按字母排序了因为后面的 PDF 排版需要有序词表。这里要给一个提醒如果同一单词在名词和动词下有不同的发音直接去重会丢信息保存成字典按词性分组会更专业但大多数人只需要一个“单词集合”排序后的列表够用。4. 用 reportlab 把结构化词表排版成适合打印的竞赛词汇 PDF4.1 页面尺寸与两栏布局A4 还是 B5竞赛词汇 PDF 的使用场景决定了页面尺寸如果只是电脑上看A4 单栏最舒服如果要打印成口袋本B5 甚至 A5 双栏更合适。我用 reportlab 做两栏时最关心的参数是colWidths和topMargin。下面这个脚本生成一个最简的 A4 双栏 PDF左边是单词右边是释义from reportlab.lib.pagesizes import A4 from reportlab.lib.units import cm from reportlab.lib.styles import ParagraphStyle from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph from reportlab.lib import colors PAGE_W, PAGE_H A4 left_margin 1.5 * cm right_margin 1.5 * cm usable_width PAGE_W - left_margin - right_margin col1_width 4.5 * cm col2_width usable_width - col1_width def build_pdf(entries, filename): doc SimpleDocTemplate( filename, pagesizeA4, leftMarginleft_margin, rightMarginright_margin, topMargin1.2 * cm, bottomMargin1.2 * cm, ) style ParagraphStyle( nameentry, fontNameHelvetica, fontSize10, leading14, wordWrapCJK, ) table_data [] for word, pos, meaning in entries: table_data.append([Paragraph(fb{word}/b, style), Paragraph(f{pos} {meaning}, style)]) table Table(table_data, colWidths[col1_width, col2_width]) table.setStyle(TableStyle([ (LINEBELOW, (0, 0), (-1, -1), 0.2, colors.lightgrey), (VALIGN, (0, 0), (-1, -1), TOP), (LEFTPADDING, (0, 0), (-1, -1), 4), (RIGHTPADDING, (0, 0), (-1, -1), 4), (TOPPADDING, (0, 0), (-1, -1), 3), (BOTTOMPADDING, (0, 0), (-1, -1), 3), ])) doc.build([table]) # entries [(abandon, v., 放弃抛弃), ...]这段代码里的wordWrapCJK特别关键。reportlab 默认对英文单词断行遇到很长的中文释义会把行排得参差不齐开启 CJK 换行后中文标点和汉字都能正确折行。另外我用Paragraph而不是纯字符串放进表格是为了让b标签能给单词加粗打印出来更清晰。4.2 支持音标的字体设置用内置的Helvetica无法显示国际音标比如ˈæbəndən里的ˈ和ə在标准西文字体里可能是豆腐块或乱码。我一般下载开源的Charis SIL字体它专为音标设计。reportlab 里注册 TTF 字体的命令是from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont pdfmetrics.registerFont(TTFont(CharisSIL, CharisSIL-Regular.ttf)) pdfmetrics.registerFont(TTFont(CharisSIL-Bold, CharisSIL-Bold.ttf))注册之后ParagraphStyle里的fontName直接写CharisSIL即可。打印前要先在本地 PDF 阅读器里放大检查一遍带ə、ɪ、ʊ的页面因为这些字符在不同字体的字形高度差异很大可能顶破行距。如果你不想下载字体还有一个妥协方案用 Unicode 字符集中的ˈ、ˌ配合DejaVu Sans字体显示效果比 Helvetica 好但不如 Charis SIL 专业。4.3 加索引和多级频率标记竞赛词汇 PDF 不能只是一张长表格用户需要按字母快速跳转。reportlab 支持 PDF 书签但生成书签需要自己算页码比较麻烦。我更喜欢在每页顶部画一个“本章字母”的标签同时在 PDF 书签里用canvas.bookmarkPage注册。下面这段代码嵌在doc.build之后可以手动添加书签但不是必需。更实用的做法是给词条按频率加背景色。竞赛词汇常见的分级是“核心、高频、低频”我从>row_bg [] for i, (word, freq) in enumerate(word_freq_pairs): if freq 5: row_bg.append((BACKGROUND, (0, i), (-1, i), colors.HexColor(#ffdcdc))) elif freq 3: row_bg.append((BACKGROUND, (0, i), (-1, i), colors.HexColor(#fff3cd)))这样打印出来高频词是浅红底中频是浅黄底低频是白底。用户第一遍背核心第二遍背全表不用再手动标重点。5. 把词汇 PDF 变成可背诵的 Anki 牌组并保留 PDF 原文定位5.1 从 JSON 生成 Anki 可导入的 CSV许多人背单词喜欢用 Anki 间隔重复。但手动一张张建卡片太慢我会把前面提取出的 JSON 转成字段1,字段2,字段3的 CSV再用 Anki 的“导入”功能批量建卡。注意 Anki 默认分隔符是英文逗号字段内容里如果含有逗号会被切错所以我会用 Tab 分隔并在导入界面选择“制表符分隔”。import csv import json with open(neccl_words.json, r, encodingutf-8) as f: words json.load(f) with open(anki_import.txt, w, encodingutf-8) as f: for item in words: # 假设 json 里每个 item 是 {word: ..., pos: ..., meaning: ...} line f{item[word]}\t{item[pos]}\t{item[meaning]} f.write(line \n)在 Anki 导入时选择同一张卡片类型把字段映射成“单词”“释义”“音标”。注意卡片类型里的第一个字段不能为空否则整行会被忽略。另外音标如果不在上面 JSON 里我建议暂时留空不要用乱码字符填上。5.2 卡片字段设计让“回忆”不只是“看到释义”竞赛词汇题里经常考的是“熟词僻义”或“搭配”所以卡片字段不能只是“英文→中文”这么简单。我在做词表时会维护一个额外字段叫“真题例句”从 PDF 里截取包含该单词的原句。如果原始 PDF 提取的例句是乱的那就先用一个占位字段等后面处理 PDF 时再补。Anki 卡片正面模板可以写成div classword{{单词}}/div div classphonetic{{音标}}/div背面模板div{{释义}}/div div{{例句}}/div5.3 用“页码链接”回查 PDF 原句的上下文Anki 卡片里直接贴大段例句会拉长复习时间更聪明的方法是只记“页码 单词序号”复习时用 PDF 阅读器跳转。我生成 PDF 时会给每个词条增加一个不可见的锚点#word_abandon并存进 JSON。Anki 卡片的“备注”字段里写PDF 第 32 页第 7 词这样背不出来的词手动翻 PDF 找到它视觉记忆会和上下文绑定。具体做法是在 reportlab 里给每个 Table 行加书签标记。实际上 reportlab 不支持行级书签只能用 Paragraph 的anchor属性。我通常会放弃复杂方案直接在词条前加上{link: abandon}然后在生成 PDF 时对每个词条调用Paragraph并设置nameword。这样导出的 PDF 在阅读器里搜索Abandon就能定位。Anki 卡片里则用一个重定向链接比如file:///D:/neccl.pdf#page32这个链接在电脑端有效手机端看情况所以我会同时保留页码文字。6. 验证 PDF 词汇覆盖率并解决打印乱码问题6.1 用 Python 统计你的词表覆盖了往年真题多少比例做出来的词表到底准不准要看它能不能覆盖竞赛真题里的超纲词。我一般把往年真题 PDF 转成纯文本然后和词表做交集统计。pip install pdfplumber pypdf统计脚本from pdfplumber import open as pdf_open import json def extract_questions(pdf_path): text with pdf_open(pdf_path) as pdf: for page in pdf.pages: part page.extract_text() if part: text part \n return text questions_text extract_questions(2024_neccs_bachelor.pdf) # 简化为单词集合去掉数字、标点 import re question_words set(re.findall(r[a-zA-Z-], questions_text.lower())) with open(neccl_words.json, r, encodingutf-8) as f: vocab_entries json.load(f) vocab_words {item[word].lower() for item in vocab_entries} not_covered question_words - vocab_words coverage (len(question_words vocab_words) / len(question_words)) * 100 print(f词表覆盖真题词汇比例: {coverage:.1f}%) print(f未覆盖词条示例: {sorted(not_covered)[:20]})结果里若有大量单词未覆盖先别急着加词。先看是不是提取出“ABCD”这类选项编号或dont被拆成了don和t。我会把这些噪音词过滤掉再算否则覆盖率虚低。更准确的口径是“词形还原”后的覆盖率那要用wordfreq库或nltk的WordNetLemmatizer但这会让脚本复杂很多。对备赛而言词汇形态变化都在考纲范围内不需要做词形还原。6.2 用 qpdf 检查字体子集避免换电脑乱码PDF 打印乱码大部分不是字库没装而是字体没有嵌入。用系统里没嵌入的字体做的 PDF在别的电脑上看变成 ToFu方框。验证方法用qpdfqpdf --check neccl_vocab_final.pdf输出里如果有Font ... not embedded就需要换一种嵌入方式或者回源重做。reportlab 生成的 PDF 默认嵌入 TTF所以通常会显示embedded subset。如果拿到别人做的 PDF又没法重做可以用pdffonts工具查哪些字体缺失pdffonts neccl_original.pdf然后准备对应的字体文件用embedfont脚本补齐。但嵌入字体有版权问题所以我在自己生成时会优先用 SIL OFL 协议的字体比如 Charis SIL。6.3 打印时按“词频色块”快速定位高频词最后一个实用技巧不是生成 PDF 时的技巧而是打印策略。当你把排版好的竞赛词汇 PDF 送到打印店时记得在打印设置里勾选“灰度打印”因为前面章节里我用红色和黄色标识高频词灰度打印不会减弱深浅层次。另一个建议是把 PDF 按字母分段输出比如a-c.pdf、d-f.pdf避免单文件 500 页时打印机内存溢出。可以用pdfseparate或 Python 的pypdf分页pdfseparate -f 1 -l 90 neccl_vocab_final.pdf a-c.pdf不过pdfseparate只能一页一页拆分段输出需要循环。也可以写一个二十行的 Python 脚本批量切页。最终我打印时会选“合并到 A4 正反面”这样单词密度高翻起来比手机背词快。记住PDF 只是载体真正有效的是你每天定时翻它的时候看到第 36 页那个红色标记的单词再对照真题里它出现的位置那才是竞赛词汇 PDF 比单词 APP 值钱的地方。本文还有配套的精品资源点击获取