每個英語學渣(好吧,其實這個說的就是學渣本渣了♀)都有這樣一個夢想: 能夠一邊輕鬆愉快地看着美劇,一邊自己的英語聽力水平還能蹭蹭地往上漲 。知乎上也有很多人分享了自己通過美劇練習聽力的方法,比如說 只開英文字幕 或者 乾脆就不要字幕 。但是這兩個方法都有自己的缺點,只開英文字幕的方法雖然說避免了下意識只看中文,但是卻造成了只看字幕不聽讀音,從而練習了閱讀忽略了聽力;不開字幕的方法確實做到了強迫自己必須認真聽,可是對於很多人來說,美劇中充滿了大量的陌生詞彙,比如說:
這句話中的 betrayal 是背叛的名詞形式,可能很多人就不認識,或者說認識但是卻沒聽過他的正確發音。這樣一來,對這句話的理解就會出現障礙。美劇中還有很多類似情況,用這樣的聽力材料顯然是不適合的。爲了應對這種情況,我有了個想法:將字幕中的詞彙拆分,並進行詞頻的檢測, 如果詞頻在 4000(可以根據自己的情況進行調整)以內,則將單詞刪除,如果詞頻在 4000 以外,則單獨標註出該詞的中文 ,效果如下:
這樣一來,這句話對於我來說就沒有任何詞彙上的障礙,假如一遍聽不懂,我就可以放心大膽的再聽一遍而不必擔心是由於詞彙的問題造成的理解障礙。
下面介紹程序的大體思路:
首先觀察字幕文件,選擇後綴名爲 srt 的字幕文件用記事本打開如下(其他類型的字幕文件用記事本打開以後格式非常複雜,此處不討論):
觀察文本特點,撰寫相應的 正則表達式 。
雖然在 Python 中使用正則表達式有幾個步驟,但每一步都相當簡單。
- 用
import re
導入正則表達式模塊。 - 用
re.compile()
函數創建一個Regex
對象(記得使用原始字符串)。 - 向
Regex
對象的search()
方法傳入想查找的字符串。它返回一個Match
對象。 - 調用
Match
對象的group()
方法,返回實際匹配文本的字符串。
常用的匹配規則:
-
?
匹配零次或一次前面的分組。 -
*
匹配零次或多次前面的分組。 -
+
匹配一次或多次前面的分組。 -
{n}
匹配 n 次前面的分組。 -
{n,}
匹配 n 次或更多前面的分組。 -
{,m}
匹配零次到 m 次前面的分組。 -
{n,m}
匹配至少 n 次、至多 m 次前面的分組。 -
{n,m}?
或*?
或+?
對前面的分組進行非貪心匹配。 -
^spam
意味着字符串必須以 spam 開始。 -
spam$
意味着字符串必須以 spam 結束。 -
.
匹配所有字符,換行符除外。 -
\d
、\w
和\s
分別匹配數字、單詞和空格。 -
\D
、\W
和\S
分別匹配出數字、單詞和空格之外的所有字符。 -
[abc]
匹配方括號內的任意字符(諸如 a、b 或 c)。 -
[^abc]
匹配不在方括號內的任意字符
Python中轉義字符使用倒斜槓(\
)。字符串'\n'
表示一個換行字符,而不是倒斜槓加上一個小寫的n。你需要輸入轉義字符\\
,才能打印出一個倒斜槓。所以'\\n'
表示一個倒斜槓加上一個小寫的 n。但是,通過在字符串的第一個引號之前加上r
,可以將該字符串標記爲原始字符串,它不包括轉義字符。輸入r'\d\d\d-\d\d\d-\d\d\d\d'
,比輸入'\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d'
要容易得多。
由上述相應規則結合文本特點得到:
#空行、行數標號正則表達式
rgx_none_and_num = re.compile(r'\d{1,2}\n')
#時間正則表達式
rgx_time = re.compile(r'\d\d:\d\d:\d\d,\d\d\d --> \d\d:\d\d:\d\d,\d\d\d\n')
之後,因爲要查詢詞頻,我在事先已經準備好了詞頻表:
要處理表格,需要用到 openpyxl 模塊,下面是從電子表格文件中讀取單元格涉及的所有函數、方法和數據類型。
- 導入
openpyxl
模塊。 - 調用
openpyxl.load_workbook()
函數。 - 取得
Workbook
對象。 - 調用
get_active_sheet()
或get_sheet_by_name()
工作簿方法。 - 取得
Worksheet
對象。 - 使用索引或工作表的
cell()
方法,帶上row
和column
關鍵字參數。 - 取得
Cell
對象。 - 讀取
Cell
對象的value
屬性。
由上述結合表格內容,建立詞庫字典:
#詞頻在4000以後的字典:
wordlist4001 = {}
#事先將名爲“1-20000.xlsx”的詞頻表放在當前工作目錄
excel_content = openpyxl.load_workbook('1-20000.xlsx')
sheet = excel_content['Sheet1']
for row in range(4000,20201):
wordlist4001[sheet.cell(row,1).value] = sheet.cell(row,2).value
#詞頻在4000以前的字典:
wordlist4000 = {}
for row in range(1,4001):
wordlist4000[sheet.cell(row,1).value] = sheet.cell(row,2).value
所有準備工作完成後,開始讀取字幕文件和處理字幕文件,最後新建一個處理過後的字幕文件。完整程序如下:
# -*- coding:utf-8 -*-
#導入模塊
import re,openpyxl
#讀入字幕文件
text=open('The.Big.Bang.Theory.s05e05.720p.x264.chs&eng.srt','r')
#空行、行數標號正則表達式
rgx_none_and_num = re.compile(r'\d{1,2}\n')
#時間正則表達式
rgx_time = re.compile(r'\d\d:\d\d:\d\d,\d\d\d --> \d\d:\d\d:\d\d,\d\d\d\n')
#處理字幕文件
first_step = text.readlines()
#新建一個字幕文件
new_file = open('C:\\Users\\SYQ\Desktop\\處理版.srt','w')
#建立4000後的字典
wordlist4001 = {}
excel_content = openpyxl.load_workbook('1-20000.xlsx')
sheet = excel_content['Sheet1']
for row in range(4000,20201):
wordlist4001[sheet.cell(row,1).value] = sheet.cell(row,2).value
#建立4000前的字典
wordlist4000 = {}
for row in range(1,4001):
wordlist4000[sheet.cell(row,1).value] = sheet.cell(row,2).value
#挑選出文字行進行處理
for line in first_step:
#如果爲空行,行數標號,則不動
if rgx_none_and_num.search(line):
new_file.write(line)
#如果爲時間行則不動
elif rgx_time.search(line):
new_file.write(line)
#如果爲字幕行,則處理
else:
words = line.lower().split()
for word in words:
#如果單詞不在字典中,則跳過
if word in wordlist4000:
pass
#如果單詞在字典中,則添加翻譯
elif word not in wordlist4001:
pass
else:
new_word = word + ':' + wordlist4001[word] +'\n'
new_file.write(new_word)
#關閉文件
text.close()
new_file.close()
因爲我也是一個 python 初學者,因此在實現這個想法的過程中也遇到了很多問題,最後實現的方法可能也顯得很笨拙,但是最後實現了還是很開心的,哈哈哈。
----------
本文是我們編程教室新春徵稿活動的一篇投稿,來自作者 @ 司夜 。他和我們很多讀者一樣,學習 python 的時間並不長,但已經把 python 應用到自己的日常學習生活中,並整理成文投稿給我們,這很值得肯定。 在實踐中應用 和 向他人講解 都是非常好的學習方式。不用在意自己寫的代碼還不夠完善, Done is better than perfect!
我們編程教室會持續向所有人開放,如果有投稿或參與志願者的意向,歡迎隨時在公衆號裏給我們留言。
另外,關於編程與英語的結合,我們之前也有過不少文章,感興趣的可以閱讀:
Crossin:我們用程序整理出了一份Python英語高頻詞彙表,拿走不謝!
分享一個強大的英漢詞典開源數據庫
英語 vs 編程
【每週一坑】單詞本 (此係列可在公衆號“ 每週一坑 ”欄目中查看)
════
其他文章及回答:
學編程:如何自學Python | 新手引導 | 一圖學Python
歡迎搜索及關注: Crossin的編程教室