0、问题描述:
实验一:语料库统计,基于词表的分词
任务1:针对人民日报语料库,编写程序实现以下功能:
【功能1】、抽取中文词表【即:去掉除了中文汉字以外的所有字符,比如数字,标点符号等
,最后只保留汉字】
【功能2】、统计上面抽取的词表的总词数
,并且提取每个不重复的词
以及该词出现的次数
,也就是词频
(词出现的频率)。
如:
总词数:99999
#词1:100
#词2:900
……
#词n:10
有同学说需要对词频进行排序输出。所以一下代码我添加了此功能。
【功能3】、去除语料库中
(注意,不是上面操作完成后的中文词表,因为只是去掉标点符号,数字之类的仍然保留
)的分词标记和词性标注,形成一个连标点符号都没有
的原始文本。
如:我爱你520
我爱你吗你是猪吗可能是吧
任务2:基于上面的【功能1】抽取的词表
,实现一个正向最大匹配分词
程序。
功能示例:
输入:没有分过词的文件/文本
输出:分了词的文件/文本
1、最后只保留汉字
"""
【功能1】、 抽取中文词表【即:去掉除了中文符号外的所有字符,比如数字,标点符号等】
"""
# 导入re功能包:
import re
# 代码开始分界线
print("------------任务1--功能1--START--------------")
# 指定正则匹配规则:匹配汉字,因为只需要保留汉字,union编码汉字范围:[\u4e00-\u9fa5]
ZStr = u"[^(\u4e00-\u9fa5)]+"
# ZStr = r"[0-9]|[-]|[/]|[a-z]|[(]|[)]"
# 1、打开文件,并操作文件
# 先清空该文件内的东西,因为一下需要使用【追加a】的方式循环操作该文件
with open("txt实验一1抽取中文词表.txt", "w", encoding="utf-8") as ff:
ff.write("") # 清空该文件的内容
with open("txt实验一1抽取中文词表不换行.txt", "w", encoding="utf-8") as ff:
ff.write("") # 清空该文件的内容
with open("199801.txt", "r", encoding="utf-8") as f:
with open("txt实验一1抽取中文词表.txt", "a", encoding="utf-8") as ff:
with open("txt实验一1抽取中文词表不换行.txt", "a", encoding="utf-8") as fff:
while True:
文件一行 = f.readline() # 每次仅读一行,防止内存卡爆
# 如果是文件末尾:退出循环
if not 文件一行: # 相当于:if 文件一行=="",即读取到一个字符串空串,注意空行代表换行符\n,所以也算一个字符,不会被当作空串
break
if 文件一行 != "\n": # 文件不是空行
替换字符串 = re.sub(ZStr, "\n", 文件一行)
# 写入文件:
ff.write(替换字符串)
替换字符串 = re.sub(ZStr, "", 文件一行)
fff.write(替换字符串)
# 2s 运行结束提示
print("------------任务1--功能1--E N D--------------")
2
"""
【功能2】、统计上面抽取的词表的总词数,并且提取每个不重复的词以及该词出现的个数。
如:
总词数:****
#词1:100
#词2:900
……
#词n:10
1、统计总词数
2、不同的词:词频
实现思路:字典:
词:词频
key:value
"""
import re
print("------------任务1--功能2--START--------------")
counts = 0 # 总词数
字典 = dict() # 使用字典来存储: 词:词频,因为字典就是Key:Value的数据格式。
# 1、打开文件,并操作文件:
with open("txt实验一1抽取中文词表.txt", "r", encoding="utf-8") as f:
while True:
文件一行一词 = f.readline() # 每次仅读一行,防止内存卡爆
# 如果是文件末尾:退出循环
if not 文件一行一词: # 相当于:if 文件一行=="",即读取到一个字符串空串,注意空行代表换行符\n,所以也算一个字符,不会被当作空串
break
if 文件一行一词 != "\n": # 文件不是空行,就代表一个词
counts += 1
文件一行一词 = re.sub("\n", "", 文件一行一词) # 去掉空格:即用空串替换换行符
if 字典.get(文件一行一词, 0) == 0: # 如果键不存在,代表还没有遇到该词、或者该词不需要
字典[文件一行一词] = 1 # 字典的value:代表词频为仅出现一次
else: # 字典的key已存在,则词频加1
字典[文件一行一词] += 1 # 字典的value:自加1
#上面的循环操作已经使得字典中存在`词:词频`,
with open("txt实验一2抽取无重复词表.txt", "w", encoding="utf-8") as f:
f.write("")
with open("txt实验一2词频词表.txt", "w", encoding="utf-8") as ff:
ff.write("")
# 将字典的key存入文件中,生成一个无重复词表
with open("txt实验一2词频词表.txt", "a", encoding="utf-8") as f:
with open("txt实验一2抽取无重复词表.txt", "a", encoding="utf-8") as ff:
for k in 字典:
f.write("#"+k + ":"+str(字典[k])+"\n")
ff.write(k + "\n")
# print("#%s : %s" % (str(k), str(字典[k])))
print("总词数:", counts) # 总词数: 936843
print("无重复的总词数:", len(字典)) # 无重复的总词数: 51360
# 4s 运行结束
print("------------任务1--功能2--END--------------")
------------------------------------------------------------------------
# 使用sorted函数对字典进行排序:
排序后得到的列表 = sorted(字典.items(), key=lambda x: x[1], reverse=False) # 按照第二个元素(value)进行排序
# print(排序后的新字典) # 输出排序后的字典(不需要分行)
# 如果需要直接分行输出:
# for i in 排序后得到的列表:
# print(i, "\n", end="")
# 如果需要使用到循环来分别输出打印key和value:也就是方便数字在前面
新字典 = dict(排序后得到的列表) # 先转换成字典
for k, v in 新字典.items():
print(v, k, "\n", end="")
3
"""
【功能3】、去除语料库中的分词标记和词性标注,形成一个连标点符号都没有的原始文本。
如:我爱你520我爱你吗你是猪吗可能是吧
思路:用正则表达式匹配【空格】或【换行符\n】或【/】或【a-z】
"""
import re
print("------------任务1--功能2--START--------------")
ZStr = "[ ]|[\n]|[/]|[a-z]"
with open("txt实验一1抽取原始文本.txt", "w", encoding="utf-8") as f:
f.write("")
with open("199801.txt", "r", encoding="utf-8") as f:
with open("txt实验一1抽取原始文本.txt", "a", encoding="utf-8") as ff:
while True:
文件一行 = f.readline() # 每次仅读一行,防止内存卡爆
# 如果是文件末尾:退出循环
if not 文件一行: # 相当于:if 文件一行=="",即读取到一个字符串空串,注意空行代表换行符\n,所以也算一个字符,不会被当作空串
break
if 文件一行 != "\n": # 文件不是空行
文件一行 = re.sub(ZStr, "", 文件一行)
ff.write(文件一行) # 写入文件
# 3s 运行结束
print("------------任务1--功能2--END--------------")
print("------------提取原始文本结束----------")
4
任务2:基于上面的【功能1】抽取的词表,实现一个【正向最大匹配分词】程序。
功能示例:
输入:没有分过词的文件/文本
输出:分了词的文件/文本
"""
功能:基于词表的分词:正向最大匹配分词算法的实现
思路:
1、将词从词表文件中读取出来,并用一个集合存储。
2、
"""
# 打开——>读取文件:
# 将文件的词读取出来,并存到集合中
import re
集合 = set()
print("----------读取文件,存入集合中----------")
with open("txt实验一2抽取无重复词表.txt", "r", encoding="utf-8") as f:
while True:
一行 = f.readline() # 每次循环————从文件中读取一行到内存中,一行即一个词
if not 一行: # 当读取到的字符串为空,跳出循环
break
词 = re.sub("\n", "", 一行) # 去掉空格:即用空串替换掉换行符
集合.add(词) # 将词加入集合中
# print(集合) # 测试语句
print("集合长度:", len(集合)) # 测试语句:集合长度: 51360
print("----------读取文件,存入集合结束----------")
# 初始化:
s2 = "" # 分好的词组成的串,虽然字符串是不可变,但是我们仍然把他的名字固定好了
s1 = input("请输入要切分的句子:") # 需要切分的字符串句子
maxLen = int(input("请输入分词的最大词长(不要太大,建议4左右):"))
print("----------开始执行正向最大匹配分词算法中----------\n")
while len(s1) > 0: # 当s1不为空的时候
w = s1[:maxLen] # 切片操作:
# print("每轮初始值w:" + w)
if 集合.isdisjoint({w}): # w 不在集合中:
while True:
if len(w) > 1: # 长度大于1,即不是单字,就需要去掉最后一个字
w = w[:- 1]
if len(w) <= 1 or (not 集合.isdisjoint({w})):
break
s2 = s2 + w + "/"
s1 = s1[len(w):]
print(s2+'\n') # 输出
print("----------正向最大匹配分词算法执行结束----------")
# 你认为学生会听老师的吗,我家门前的小河很难过