前言
最近接了做字幕的兼职,自己总结了一套效率比较高的流程,但其中有一步需要将混在一起的中文行和英文行分开,所以想到了借助Python脚本来解决。
本来觉得是个没那么复杂的问题,就是检测某一行是否包括中文即可,不过由于对编码问题的不熟悉,花了不少功夫。
(建议大家尽快转用Python3,此类问题会少很多。。。)
正文
编码溯源
1.为了处理英文字符,产生了ASCII码。
2.为了处理中文字符,产生了GB2312。
3.为了处理各国字符,产生了Unicode。注意Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
4.为了提高Unicode存储和传输性能,产生了UTF-8,它是Unicode的一种实现形式。
UTF-8与BOM
Windows下使用UTF-8编码默认会在文件头加BOM(byte order mark),它是为 UTF-16 和 UTF-32 准备的,用于标记字节序(byte order)。
尽管 Unicode 标准允许在 UTF-8 中使用 BOM,但它并不是必要的。特别地,UTF-8 的网页代码不应使用 BOM。
微软在 UTF-8 中使用 BOM 是因为这样可以把 UTF-8 和 ASCII 等编码明确区分开,但这样的文件在 Windows 之外的操作系统里会带来问题。
而使用Notepad++可以将文本文件的编码格式转换为无BOM的UFT-8编码格式。
系统编码
系统的默认编码有所不同(这里指控制台显示的编码):Linux默认UTF-8,Windows(简体中文)默认GB2312。
因此直接用Windows控制台输出UTF-8编码格式的中文会出现乱码,就是因为编译码方式不同,导致解析错误。
源码中的编码
Python2会将整个python脚本中的内容当做ASCII码去处理,因此在文件头部加入一行编码声明如:
# -*-coding:utf8-*-
这样,Python在处理这个脚本时,会用UTF-8的编码去处理整个脚本,就能够正确的解析中文字符了。
字符串中的编码
Python2中的字符串有str和Unicode两种类型。
str类型的字符串都有一定的编码方式,如ASCII、GBK、UTF-8等等,而Unicode即为无编码格式的计算机存储符号。
通过encode和decode函数可以在两者间进行转换
可以观察到UNICODE编码的串输出时在整个字符串前带一个'u'的前缀,每个UNICODE符也各自含有一个'\u'的开头。
查资料知基本汉字的UNICODE范围在4E00-9FA5之间,简略地使用这个范围便足以满足我们的需求。
参考资料
字符编码笔记:ASCII,Unicode 和 UTF-8(强烈推荐)
附代码
# -*-coding:utf8-*-
#首先需将中英文字幕文件编码格式修改为UFT-8无BOM编码格式,并将其放置在所确定的路径
#转换结束后再将文件修改回UFT-8编码格式,或者不转好像也行 ^_^
def have_Chinese(word):
for ch in word.decode('utf-8'):
if u'\u4e00' <= ch <= u'\u9fff':
return True
return False
#路径修改为翻译字幕所在路径
path = "D:\\Desktop\\"
#翻译字幕文件名
file = path+"Subtitles.txt"
#视频题目
title = path+"Video"
with open(file,'r') as f:
lines = f.readlines()
Cn=[]
Eng=[]
for line in lines:
if len(line) <= 8: #这意味着空码,包含时间码和换行符
Cn.append(line)
Eng.append(line)
continue
if have_Chinese(line): #行内包含中文则视为中文字幕
Cn.append(line)
else:
Eng.append(line) #否则为英文字幕
with open(title+'.txt','w') as res_Eng:
for line in Eng:
res_Eng.write(line)
with open(title+'_CN.txt','w') as res_Cn:
for line in Cn:
res_Cn.write(line)