下载的sougou中文语料文件是xml格式的,有1.5G,需要在python下进行正文的提取及中文分词工作。
1. 首先,进行正文的提取,有几个需要注意的细节。
a. 检测文件的中文编码
在python下安装chardet包,使用chardet检查中文格式. 注意读文件时使用的是'rb'.
b. 读取原始数据
在获取了中文编码格式后,使用codecs包,注意参数errors="ignore"的使用,否则会出现以下类似错误:
UnicodeDecodeError: 'gb2312' codec can't decode byte 0xfd in position 440: illegal multibyte sequence
c. 在处理大的文件时,for循环里不要做类似以下的操作,否则速度非常慢。
text_str = '';
for item in a:
b = item.replace('<content>','');
text_str = text_str + (b.replace('</content>',''));
读大文件,linecache.getlines也可以用于加速文件操作。
d. 在写入文件时,特意增加了'\n',这样方便后续的“按行读文件”操作。
(增加换行符后的文本,在notepad++里的显示如下图,因为有个分行和行号,看起来很方便。)
完整的代码如下:
import chardet
import codecs
import re
def detect_file_encoding(file_path):
''' 返回文件的编码 '''
f = open(file_path, 'rb')
data = f.read()
predict = chardet.detect(data)
f.close()
return predict['encoding']
if __name__ == '__main__':
# detect file encode type
file_path = r'D:\Work\NLP\Dataset\new\sogou\news_tensite_xml.dat';
print( detect_file_encoding(file_path) )
# read file
f2 = codecs.open(file_path, encoding='GB2312', errors="ignore")
content2 = f2.read();
f2.close()
# write to text file
f = codecs.open(r'D:\Work\NLP\Dataset\new\sogou\output\news_tensite_xml.txt', 'w',encoding='utf8');
# exact the text between <content> and </content>
a = re.findall('<content>.*</content>', content2)
print("Length of list: %d" % len(a));
i = 0;
for item in a:
b = item.replace('<content>','');
b = b.replace('</content>','');
f.write(str(b)+'\n');
i = i+1;
if i%1000 == 0:
print("index: %d / %d" % (i,len(a)));
f.close();
2. 使用jieba进行中文分词工作,完整代码如下。
这里需要注意的是,输入给jiebad的是每行字符串,而不是整个文件作为字符串(太大了)。
import jieba
import codecs
import datetime
inp = r'D:\Work\NLP\Dataset\new\sogou\tmp\news_tensite_xml.txt';
outp = r'D:\Work\NLP\Dataset\new\sogou\output\news_tensite_xml_segment.txt';
finput = codecs.open(inp, encoding='utf8', errors="ignore")
foutput = codecs.open(outp, 'w',encoding='utf8');
space = " ";
i = 0;
start = datetime.datetime.now()
for line in finput:
i = i+1;
if i%1000 == 0:
print(i);
line_seg = jieba.cut(line)
foutput.write(space.join(line_seg));
end = datetime.datetime.now()
print (end-start)
finput.close()
foutput.close()
附加: 使用以上分词的结果进行word2vec训练,代码如下。
# -*- coding: utf-8 -*-
# train_word2vec_model.py用于训练模型
import logging
import os.path
import sys
import multiprocessing
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
import datetime
if __name__=='__main__':
program = os.path.basename(sys.argv[0])
logger = logging.getLogger(program)
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
logging.root.setLevel(level=logging.INFO)
logging.info("running %s" % ' '.join(sys.argv))
#inp = r'D:\Work\NLP\Dataset\new\sogou\output\news_tensite_xml.smarty_segment.txt';
#outp = r'D:\Work\NLP\Dataset\new\sogou\output\news_tensite_xml.smarty_corpus.mode';
#outp2 = r'D:\Work\NLP\Dataset\new\sogou\output\news_tensite_xml.smarty_corpus.vector';
inp = r'D:\Work\NLP\Dataset\new\sogou\output\news_tensite_xml_segment.txt';
outp = r'D:\Work\NLP\Dataset\new\sogou\output\news_tensite_xml_corpus.mode';
outp2 = r'D:\Work\NLP\Dataset\new\sogou\output\news_tensite_xml_corpus.vector';
start = datetime.datetime.now()
model = Word2Vec(LineSentence(inp),size=400,window=5,min_count=5)
model.save(outp)
model.wv.save_word2vec_format(outp2,binary=False)
end = datetime.datetime.now()
print (end-start)
附加: 训练完后测试word2vec,代码如下。
import gensim
model = gensim.models.Word2Vec.load(r'D:\Work\NLP\Dataset\new\sogou\output\news_tensite_xml_corpus.mode')
result = model.most_similar(u'喜欢')
for word in result:
print( word[0],word[1] )
得到的结果如下: