下载的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] )
得到的结果如下: