Python词频统计之密信约定进攻时间

问题

假设你是小蔡,你和小徐同学一起穿越到了抗战时期,分别成为了八路军华北根据地A地和B地的联络员。此时,两地的八路军部队准备发动协同进攻,给予日寇重重一击。由于某些原因无法亲自送信,为了约定进攻时间,小徐只能通过伪军的邮政系统寄送密信。信上的信息看起来平平无奇(如666.txt所示),只有若干行文字……直到你看到了正文最后一段文字: “小蔡,还记得咱上Python课的时候,学的词频统计吗?咱当时只会统计前四个词,还没学其他的。我相信,我们最终一定能回到和平幸福的新时代,那时我们会重逢的,勿念。” 现在,你收到了这封密信,发现自己带过去的笔记本电脑还有电。请根据所学的词频统计知识,使用jieba库编写程序,统计信中各个词语的词频并按词频降序排列词语;之后找出规律,以字符串形式输出秘密情报的关键内容,获得发动进攻的时间信息。

e6f636861b2b484b99897933db0a6977.png

 

信的内容如下(放在一个名为666的文本里面):

小蔡啊:
    好久不见!不知道你过得怎么样,还好当时有所准备,我带过来的东西,除了钱,除了手机,除了充电器,除了银行卡,除了校园卡,除了笔记本,都还能用。
    我还记得咱们离开那个世界时,天边还是夕阳,穿越的那个地方有点偏,周围没有一个行人,连动物都没有,不知道动物们去哪了。可能是夕阳告诉动物们,该休息了吧。
    我给你写这个信的时候,周围行人还挺多的,但是行人都忙着逃荒,在夕阳下显得有点伤感。每一次看到夕阳,每一次行人走过,我都希望看到你出现。在这个年代,不晓得还有几次看见夕阳的机会。
    小蔡,还记得咱上Python课的时候,学的词频统计吗?咱当时只会统计前四个词,还没学其他的。我相信,我们最终一定能回到和平幸福的新时代,那时我们会重逢的,勿念。

 

解析

首先打开那个文件并且读取,用jieba库的lcut()方法进行精确模式切分中文词语,这个方法会将切分好的词语作为列表类型返回,然后再进行词语的计数并且降序输出,最后再查找规律

1,打开文件

这里直接用with的方式打开文件:

import jieba
import codecs

wenjian=input("输入文件路径:\n")
with codecs.open(wenjian,'r+','utf-8')as fp:
    a=fp.read()
    
b=jieba.lcut(a)

输入方式是输入一个文件的一个路径

77efc446c2b64be6967c6c7886b60458.png

你们可以存放在这个项目里面,到时候就直接输入666.txt好了 

如果用codecs这个库,再加上with的方式来打开文件,就不再用close()的方式去关闭文件,执行过后会自动关闭,并且大大提高安全性,你也可以用io这个库,不过可能会出一点问题,为了方便我就直接用codecs了

然后就是a接收文件里面的内容,b就接收把a切分好的列表类型数据

2.除杂并且计数

去掉一些不必要的字符,比如单个字符和一些符号:

d = {}  # 定义一个空字典
for i in b:  
    if i == '\r\n':
        continue  #因为该文件夹有大量\r\n,需要清理掉
    if len(i)==1:
        continue
    else:
        d[i] = b.count(i)#count是一个计数方法

在除杂的时候,可以进行一些计数操作,count()这个方法就是来计数的,还有d是一个字典类型,规则是这样的:{<键>:<值>},其中类似下标的,就是键,用键来存储数据,而另外的值,就是储存计数。                                                                                                                                            如上面的 d[i] = b.count(i)  ,i是b里面的一个数据,用这个方法会统计b里面全部跟 i 相同的数据,然后统计完再赋值给键为 i 的字典,此时字典就是{<i>:<为i的计数>}

这样除杂的时候顺便也统计了,下一步就是排序

3.排序

items=list(d.items())#列表化
items.sort(key=lambda x:x[1], reverse=True)#x:x[1]以第二个元素排序,x:x[0]以第一个元素排序

item()方法把字典中每对key和value组成一个元组,可以把它转化为列表类型,再用sort()方法进行排序,因为sort()是列表类型的,所以转换类型很有必要

key=lamda x:x[1]这个的意思是以值作为排序标准,也就是文中的计数大小作为标准,reverse接受的是一个bool类型的值 (Ture or False),表示降序还是升序,一般默认的是False,也就是升序,注意第一个字母是大写的

排序完,就是输出了

4.输出

i=0
while i<len(items):  # 遍历
    key,count=items[i]
    print("{0:<10}{1:>5}".format(key, count))
    i=i+1

因为item一个下标是储存着两个数据的,所以 key,count=items[i],key就是那个键,count也就是那个数量

还是很好理解的,输出就是这个了

除了            6
夕阳            5
行人            4
动物            3
知道            2
当时            2
记得            2
那个            2
有点            2
周围            2
没有            2
这个            2
时候            2
一次            2
看到            2
统计            2
我们            2
好久不见          1
怎么样           1
还好            1
有所准备          1
我带            1
过来            1
东西            1
手机            1
充电器           1
银行卡           1
校园卡           1
笔记本           1
咱们            1
离开            1
世界            1
天边            1
还是            1
穿越            1
地方            1
一个            1
可能            1
告诉            1
休息            1
但是            1
逃荒            1
显得            1
伤感            1
走过            1
希望            1
出现            1
年代            1
晓得            1
还有            1
几次            1
看见            1
机会            1
咱上            1
Python        1
词频            1
只会            1
四个            1
没学            1
其他            1
相信            1
最终            1
一定            1
回到            1
和平            1
幸福            1
时代            1
那时            1
重逢            1
勿念            1

附上源代码(该源码不是题目答案,下面最终代码才是):

import jieba
import codecs

wenjian=input("输入文件路径:\n")
with codecs.open(wenjian,'r+','utf-8')as fp:
    a=fp.read()

b=jieba.lcut(a)


d = {}  # 定义一个空字典
for i in b:  #
    if i == '\r\n':
        continue  #因为该文件夹有大量\r\n,需要清理掉
    if len(i)==1:
        continue
    else:
        d[i] = b.count(i)#count是一个计数方法
items=list(d.items())#列表化
items.sort(key=lambda x:x[1], reverse=True)#x:x[1]以第二个元素排序,x:x[0]以第一个元素排序
i=0
while i<len(items):  # 遍历
    key,count=items[i]
    print("{0:<10}{1:>5}".format(key, count))
    i=i+1

5.查找线索规律:

规律大概是这样,最后一句话有提示,说咱们只会统计前四个词,我们可以输出一下最初四个词是这样的:

'小', '蔡', '啊', ':', '\r\n', ' ', ' ', ' ', ' ', '好久不见', '!', '不', '知道', '你', '过', '得', '怎么样', ',', '还好'

这是我截取的前四个词语,当然单个字和符号不算,我们往上去找那个全部输出,可以发现

'好久不见'    为1, '知道'    为 2, '怎么样'   为1, '还好'  为1,再将其进行倒序

显然是2111

结合起来应该是21:11,这样的时间就非常合理,夜袭嘛

所以最终代码如下(只需统计前四个词的数量):

import jieba
import codecs

wenjian=input("输入文件路径:\n")
with codecs.open(wenjian,'r+','utf-8')as fp:
    a=fp.read()

b=jieba.lcut(a)

d = {}  # 定义一个空字典
p=0#记录储存了多少个数
for i in b:  #
    if i == '\r\n':
        continue  #因为该文件夹有大量\r\n,需要清理掉
    if len(i)==1:
        continue
    else:
        d[i] = b.count(i)#count是一个计数方法
        p=p+1
        if p==4:#只储存前四个词的计数
            break
items=list(d.items())#列表化
items.sort(key=lambda x:x[1], reverse=True)#x:x[1]以第二个元素排序,x:x[0]以第一个元素排序
i=0
shijian=''
while i<p:
    key,count=items[i]#将count提取出来并组成新的列表
    shijian=shijian+str(count)#字符串间可以直接加,来组成新的字符串
    i=i+1

print(shijian)

改的不是很多,你们可以对比一下两个代码就知道了

最后,为什么发两个代码呢?

第二个代码只能解答这种特定的问题,然而第一个代码却可以解答更多类似的问题

希望各位能通过我的两个代码能学到比只有第二个代码更多的知识

 

有用不妨点个免费的赞吧~~

 

 

 

 

 

 

 

 

 

 

  • 14
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值