Python实例分析(二)删除“字典”中的释义内容

Python实例分析(二)删除“字典”中的释义内容

书接上回,我们完成了删除空行之后,下一步就是将释义内容删掉。大体思路是:

每行从左起,找到第一组拼音,然后找到这组拼音的最后一个字符,截取这个字符(含)之前的内容,写入目标文件。

这个思路主要来源于源文件的结构形式,当然在实际操作中还遇到了一些困难,我们边讲边说。

判断拼音

看了实例分析(一),想必大家都知道怎么读取源文件了。那就简单列一下:

>>> f=open('/Users/gaoqy/Desktop/source.txt','r')

>>> w=open('/Users/gaoqy/Desktop/target.txt','w')

>>> data=f.readlines()

以上就是我读取的文本内容。同样我也是截取一部分做测试和演示,这个与(一)中的内容不同,因为涉及到几个问题,需要。

因为我们会用到for循环遍历每行内容,首先我们先把循环体内部的逻辑、代码弄清楚。所以,我们用line先取data列表中的一行,做测试:

>>> line = data[0]

>>> line

'【阿Q】ĀQ名鲁迅小说《阿Q正传》的主人公,是“精神胜利者”的典型,受了屈辱,不敢正视,反而用自我安慰的办法,说自己是“胜利者”。\n'

line = data[0],是将data列表中的第一个元素赋值给line。第一个元素的序号是0,第二个元素的序号是1,依次类推。

然后我们检验一下,确认line的值为data中的一个元素。以下操作,我们就针对line测试即可。

要判断拼音,我们需要先做一个拼音的集合,为什么此时是集合呢?因为集合与列表的最主要区别就是,集合中的元素是无序的、唯一的。我们的拼音只需要集合就可以了。

>>> pinyin = set('aoeiuüāōēīūǖáóéíúǘǎǒěǐǔǚàòèìùǜAOEIUÜĀŌĒĪŪǕÁÓÉÍÚǗǍǑĚǏǓǙÀÒÈÌÙǛ•∥’bpmfdtnlgɡkhjqxzcsrwyWYBPMFDTNLGKHJQXZCSRH')

这是我自己做的pinyin集合,包括了在源文件中,拼音位置出现的所有字符,包括带不同声调的韵母,还有带两个点的ü以及间隔符等等。这个集合只针对这个源文件而做,不确定有没有普适性。

做好了pinyin集合后,我们就可以用in和not in判断一个字符是否在这个集合中。先演练一下:

>>> '我' in pinyin

False

>>> '我' not in pinyin

True

>>> 'i' not in pinyin

False

>>> 'i' in pinyin

True

找到拼音的结尾

截取字符串,我们需要确定末位,也就是拼音的结尾。先用while循环确定拼音的起始位置,然后再用while循环确定拼音的结束位置。

那为什么先要判断拼音的起始位置?因为流程大概是这样的:

第一个字符是不是拼音字符? 哦,不是,下一个;

第二个字符是不是拼音字符?哦,不是,下一个;

第三个字符是不是拼音字符?哦,是,开始找结尾;

第四个字符是不是拼音字符?哦,是,下一个;

第五个字符是不是拼音字符?哦,是,下一个:

第六个字符是不是拼音字符?哦,不是,好了,就到这!

如果不先找到拼音的起始位置,那么第一字符不是拼音字符时,这个判断就已经结束了。(或许会有更好的逻辑,那另说,反正我就讲我的思路,就是这么傲娇‍♂️

我们先换一个line值:

line = data[1]

>>> line

'【阿是穴】āshìxué名中医在针灸上把没有固定名称的穴位,以酸、麻、胀、痛等感觉最明显的部位或病痛处作为穴位,叫做阿是穴。\n'

从左往右确定拼音起始位置,这里我们用i来遍历~

>>> i = 0

>>> i

>>> while line[i] not in pinyin:

... i += 1

...

前三行,先确定i为0;while循环,当line的i号字符不为拼音字符的时候,i增加1,然后循环判断,直至line的i号字符为拼音字符时停止。

>>> i = 0

>>> i

>>> while line[i] not in pinyin:

... i += 1

...

>>> i

5

>>> line[i]

'ā'

可以看到,当循环结束时,i值为5,line[i]为'ā'。line[i]确实是我们要找的“阿是穴”拼音的起始位置。

然后我们再来确定结束位置:

>>> while line[i] in pinyin:

... i += 1

...

>>> i

12

>>> line[i]

'名'

此时我们不需要初始化i的值,直接接着判断line[i]是否为拼音字符,如果是,i增加1,然后循环判断,直至line[i]不是拼音字符。

可以看到i值为12的时候,line[i]为'名',是拼音之后的第一个字符。

>>> print(line[:i])

【阿是穴】āshìxué

>>> print(line[0:i])

【阿是穴】āshìxué

找到拼音结束位置,我们就可以截取字符串了,(字符串也可以理解为一个列表)直接用字符串参数即可。这里需要注意的是,参数正常是[x:y],x是起始序号,y是数量,指的是,从第x号开始的y个元素。因为序号是从0而不是1开始,所以[0:i]刚好是指到拼音结束。

遇到问题 一

为啥刚刚在傲娇之后要换一个line值?当然,并不是我欠欠的~。我们用上述方法处理“阿Q”的词条,就发现了一个问题,词条中就出现了拼音字符!

>>> line = data[0]

>>> line

'【阿Q】ĀQ名鲁迅小说《阿Q正传》的主人公,是“精神胜利者”的典型,受了屈辱,不敢正视,反而用自我安慰的办法,说自己是“胜利者”。\n'

>>> i = 0

>>> while line[i] not in pinyin:

... i += 1

...

>>> while line[i] in pinyin:

... i += 1

...

>>> print(line[:i])

【阿Q

第一二行,我们把line的值换回成data[0],然后通过我们之前的解决方法操作,最后得到的结果是“【阿Q”,还没进入真•拼音部分,就结束了,因为词条中出现了Q,Q也是我们pinyin集合里的元素。

解决思路

用“先找到拼音起始位置”同样的思路,我们先找到词条的结尾(也就是“】”)然后再开始找拼音的起始位置……

>>> i = 0

>>> while line[i] != '】':

... i += 1

...

>>> i

3

>>> line[i]

'】'

用while循环找到'】',此时再用我们之前方法即可找到拼音的结束位置。

>>> i

3

>>> line[i]

'】'

>>> while line[i] not in pinyin:

... i += 1

...

>>> while line[i] in pinyin:

... i += 1

...

>>> print(line[:i])

【阿Q】ĀQ

注:这里的ĀQ并不是拼音,而是一个拼音加一个英文字母。鉴于这是个案,我们先不考虑这种问题的具体解决方法,只提供思路:找到【】中的英文字母,然后再找到拼音,从拼音中删掉找到的字母,这样就可以了,不过过于麻烦,这里不讲了,有兴趣可以自己试试,然后我们私下探讨。

写成py文件

套上一个遍历data列表的for循环,我们可以将上述代码写成py文件:

写完之后,兴高采烈地跑了一下source文件,结果报错了~

我们刚才的思路没问题,也是经过检验的。然后我又查看了一下报错内容,和目标文件,才发现了问题的根源。

遇到问题 二

我们看一下报错内容,第九行代码,i的值超出范围了;然后我又看了一下目标文件,正确地输出了3行:

所以,问题可能出现在源文件的第四行内容上。一定是不符合我们假设的格式。果然不出所料,第四行是个“另见1563页yān。”(如下图),这不符合我们代码所处理的格式,所以i没有遇到“】”就不停的累加,最后到写入的时候,超出了line[:i]的正确值,所以报错了。

注:这里的文档是演示用的,其实一眼就能看到这个问题,所以可以在写代码之前就做好准备,然而我在做的时候,只是大致扫了一下文档(足足8mb大小),没有注意到,因此犯了错。

解决思路

再仔细分析一下文档的结构,我们的需要的内容都是以“【”开始的,那么我们先进行一个判断,行首为“【”时,处理这行内容;行首不为“【”时,不处理这行内容,跳过即可。

所以在while循环前,加一个if条件判断:

>>> if line[0] == '【':

... print(line)

...

其实,肯定是没有问题的,不过还是来测试一下:

先用出错的那行,data[3],没有返回;再用没出错的任意一行,如data[1],返回了该行内容。说明判断起作用了,我们把它加到代码中:

第9行是新加的,10至17行需要嵌套进if判断中,所以要多加一个缩进,别忘了。

使用效果

源文件

处理后

当然具体实践过程中还遇到了很多奇葩的问题,比如编码不统一、源文件处理不规范、“g”和“ɡ”不是一个东西等等……词条后的括号内容,我也没删,担心老板会有参考之用。

其实是我懒诶

停!停!停!!

“g”和“ɡ”不是一个东西?!

️️️

对,它俩不是一个东西,有图为证:

我搜索了英文字母“g”,然而图中拼音里的“ɡ”并没有检索到(未标注),如果是同一个字符,应该如下图那样,所以这两个应该是外表极其相似的不同字符。最后都统一到英文的g了(因为输入方便)。

总之,解决了种种疑难杂症之后,才完成任务。所以写完程序后一定要检查,一定要细心。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181114G0D0U700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券