剑桥词典API实战:用Python爬取单词释义、发音和例句(附完整代码)
·
剑桥词典数据自动化采集实战:Python逆向工程与语音库构建指南
在语言学习工具开发领域,剑桥词典因其权威释义和标准发音成为众多开发者的首选数据源。本文将揭示如何通过Python技术栈实现词典数据的自动化采集,包括释义解析、发音文件下载以及例句提取,为开发者构建个性化语言学习工具提供完整技术方案。
1. 环境准备与目标分析
构建自动化采集系统前,需要明确技术路线和工具链。不同于官方API调用,我们采用网页解析与文件规律分析相结合的方式实现数据获取。
基础环境配置:
# 核心依赖库
import requests
from bs4 import BeautifulSoup
import re
import json
from urllib.parse import quote
import os
# 语音下载专用库
import wget
from pydub import AudioSegment
剑桥词典网页结构特点分析:
- 单词查询URL格式固定:
https://dictionary.cambridge.org/dictionary/english/{word} - 发音文件存储路径遵循特定命名规则
- 词性分类使用特定CSS类标识
- 例句存在于结构化HTML标签中
提示:实际操作前建议配置合理的请求间隔(如3-5秒),避免触发反爬机制
2. 网页结构逆向工程
2.1 基础请求与反爬策略
实现稳健的数据采集需要处理网络请求的各种异常情况:
def safe_request(url, max_retry=3):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept-Language': 'en-US,en;q=0.9'
}
for attempt in range(max_retry):
try:
resp = requests.get(url, headers=headers, timeout=10)
if resp.status_code == 200:
return resp
elif resp.status_code == 429:
time.sleep(10) # 请求过频处理
continue
except Exception as e:
print(f"Attempt {attempt+1} failed: {str(e)}")
time.sleep(5)
return None
2.2 关键数据定位技术
通过分析DOM结构,我们发现主要数据分布在特定标签中:
def parse_word_page(html):
soup = BeautifulSoup(html, 'html.parser')
# 词性区块定位
pos_blocks = soup.find_all('div', class_='pr entry-body__el')
data = {
'word': soup.find('span', class_='hw dhw').text,
'pronunciation': {},
'definitions': [],
'examples': []
}
# 发音文件提取逻辑
uk_audio = soup.find('source', {'type': 'audio/mpeg', 'src': re.compile('uk_pron')})
us_audio = soup.find('source', {'type': 'audio/mpeg', 'src': re.compile('us_pron')})
if uk_audio: data['pronunciation']['uk'] = uk_audio['src']
if us_audio: data['pronunciation']['us'] = us_audio['src']
# 释义提取逻辑
for block in pos_blocks:
pos = block.find('span', class_='pos dpos').text
def_blocks = block.find_all('div', class_='def-block ddef_block')
for def_block in def_blocks:
definition = def_block.find('div', class_='def ddef_d db').text
example = def_block.find('span', class_='eg deg')
data['definitions'].append({
'pos': pos,
'definition': definition,
'example': example.text if example else None
})
return data
3. 发音文件系统化采集
3.1 发音文件URL规律解析
通过分析数百个单词的发音文件路径,我们发现以下命名模式:
| 组件 | 示例 | 生成规则 |
|---|---|---|
| 首字母目录 | u | 单词首字母 |
| 二级目录 | ukn | 单词前2-3字母 |
| 三级目录 | uknot | 单词前4-5字母 |
| 文件名 | uknotif012 | 单词+数字后缀 |
实现代码:
def build_pronunciation_url(word, accent='uk'):
"""根据单词生成可能的发音文件路径"""
first_char = word[0].lower()
two_chars = word[:2].lower() if len(word) > 1 else first_char
three_chars = word[:3].lower() if len(word) > 2 else two_chars
base_url = f"https://dictionary.cambridge.org/media/english/"
path = f"{accent}_pron/{first_char}/{two_chars}/{three_chars}/"
# 尝试常见数字后缀
for i in range(1, 10):
filename = f"{three_chars}{i:02d}.mp3"
full_url = base_url + path + filename
if requests.head(full_url).status_code == 200:
return full_url
return None
3.2 语音文件处理技巧
获取音频文件后,通常需要进行格式转换和标准化处理:
def process_audio(filepath):
"""统一音频格式和质量"""
audio = AudioSegment.from_file(filepath)
# 标准化处理
audio = audio.set_frame_rate(22050)
audio = audio.set_channels(1)
audio = audio.normalize()
# 保存为标准格式
output_path = filepath.replace('.mp3', '_processed.wav')
audio.export(output_path, format='wav', bitrate='16k')
return output_path
4. 数据存储与应用集成
4.1 结构化存储方案
采集的数据建议采用混合存储策略:
def save_word_data(word_data, storage_dir):
"""保存单词数据到文件系统"""
word = word_data['word']
# 创建单词目录
word_dir = os.path.join(storage_dir, word.lower())
os.makedirs(word_dir, exist_ok=True)
# 保存JSON元数据
with open(os.path.join(word_dir, 'meta.json'), 'w') as f:
json.dump({
'definitions': word_data['definitions'],
'examples': word_data['examples']
}, f, indent=2)
# 下载发音文件
for accent, url in word_data['pronunciation'].items():
filename = f"{word}_{accent}.mp3"
wget.download(url, os.path.join(word_dir, filename))
return word_dir
4.2 数据库集成示例
对于大规模应用,建议使用MongoDB存储结构化数据:
from pymongo import MongoClient
class DictionaryDB:
def __init__(self, uri='mongodb://localhost:27017/'):
self.client = MongoClient(uri)
self.db = self.client['dictionary']
self.words = self.db['words']
def insert_word(self, word_data):
"""插入或更新单词数据"""
filter_ = {'word': word_data['word']}
self.words.replace_one(filter_, word_data, upsert=True)
def get_word(self, word):
"""查询单词数据"""
return self.words.find_one({'word': word.lower()})
5. 高级技巧与异常处理
5.1 多义词处理策略
剑桥词典中多义词的页面结构更为复杂,需要特殊处理:
def handle_polysemy(soup):
"""处理多义词情况"""
entries = []
main_entry = soup.find('div', class_='pr entry-body__el')
if not main_entry:
# 多义词情况
sense_blocks = soup.find_all('div', class_='pr dsense')
for block in sense_blocks:
headword = block.find('span', class_='hw dsense_hw')
definition = block.find('div', class_='def ddef_d db')
if headword and definition:
entries.append({
'variant': headword.text,
'definition': definition.text
})
return entries
5.2 反爬规避实战方案
长期运行的采集系统需要更完善的反反爬策略:
class SmartRequest:
def __init__(self):
self.session = requests.Session()
self.proxies = self._init_proxies()
self.current_proxy = 0
self.last_request = 0
def _init_proxies(self):
# 实现代理池初始化逻辑
return ['http://proxy1:port', 'http://proxy2:port']
def get(self, url):
# 请求速率控制
elapsed = time.time() - self.last_request
if elapsed < 2.5: # 保持合理间隔
time.sleep(2.5 - elapsed)
try:
proxy = {'http': self.proxies[self.current_proxy]}
resp = self.session.get(url, proxies=proxy, timeout=10)
if resp.status_code == 403:
self._rotate_proxy()
return self.get(url)
self.last_request = time.time()
return resp
except:
self._rotate_proxy()
return self.get(url)
def _rotate_proxy(self):
self.current_proxy = (self.current_proxy + 1) % len(self.proxies)
6. 实战应用案例
6.1 构建离线单词本
将采集的数据转化为Anki记忆卡片:
def create_anki_card(word_data):
"""生成Anki导入格式数据"""
front = f"<h1>{word_data['word']}</h1>"
back = "<div class='definitions'>"
for def_item in word_data['definitions']:
back += f"""
<div class='definition'>
<span class='pos'>{def_item['pos']}</span>
<p>{def_item['definition']}</p>
{f"<blockquote>{def_item['example']}</blockquote>" if def_item['example'] else ""}
</div>
"""
back += "</div>"
# 添加发音按钮
if word_data['pronunciation'].get('uk'):
back += f"""
<audio controls>
<source src="{word_data['pronunciation']['uk']}" type="audio/mpeg">
</audio>
"""
return [word_data['word'], front, back]
6.2 集成到翻译工具
将词典数据与翻译API结合:
class EnhancedTranslator:
def __init__(self):
self.db = DictionaryDB()
self.cache = {}
def lookup(self, word):
# 先检查缓存
if word in self.cache:
return self.cache[word]
# 查询本地数据库
db_result = self.db.get_word(word)
if db_result:
self.cache[word] = db_result
return db_result
# 实时采集
url = f"https://dictionary.cambridge.org/dictionary/english/{quote(word)}"
resp = safe_request(url)
if resp:
data = parse_word_page(resp.text)
self.db.insert_word(data)
self.cache[word] = data
return data
return None
更多推荐



所有评论(0)