背景

来自某选修课。现有Json格式的“CAIL 2018 刑事案件案例文书数据”,每条数据一行,如下:

{
    "fact": "公诉机关指控:2016年3月28日20时许,被告人颜某在本市洪山区马湖新村足球场马路边捡拾到被害人谢某的VIVOX5手机一部,并在同年3月28日21时起,分多次通过支付宝小额免密支付功能,秘密盗走被害人谢某支付宝内人民币3723元。案发后,被告人颜某家属已赔偿被害人全部损失,并取得谅解。公诉机关认为被告人颜某具有退赃、取得谅解、自愿认罪等处罚情节,建议判处被告人颜某一年以下××、××或者××,并处罚金。\r\n", 
    "meta": 
    {
    "punish_of_money": 1000, 
    "term_of_imprisonment": 
    {
        "life_imprisonment": false, 
        "death_penalty": false, 
        "imprisonment": 4
    }, 
    "criminals": ["颜某"], 
    "accusation": ["盗窃"], 
    "relevant_articles": ["264"]
    }
}

现需要统计整个数据集中特定几个罪名的“刑期分布”,比如1个月的多少个,2个月的多少个,无期的多少个……

实现

Json数据集是已经格式化的数据集,利用Python中的json库便可直接将数据集转化为Python中的dictionary数据类型。此数据类型类似于C++中的map,一个key值对应一个value值。具体代码如下:

# -*- coding: utf-8 -*-
import json

statistics = {}

#input
print "Please input five different accusations:\n"
for i in range(1, 2):
    mystr = raw_input("  input No." + str(i) + " : ")
    #mystr.encode('utf-8')
    mystr = unicode(mystr, 'utf-8')
    statistics[mystr] =\
        {
            "life": 0,
            "death": 0
        }
#process
print "\nInput ended. Start processing...\n"
index = 0
with open("train.json", 'r') as f:
    for line in f:
        index += 1
        dict_line = json.loads(line)
        dict_meta = dict_line["meta"]
        info = dict_meta["term_of_imprisonment"]
        death = info["death_penalty"]
        life = info["life_imprisonment"]
        last = info["imprisonment"]
        for accu in dict_meta["accusation"]:
            if statistics.has_key(accu):
                if death:
                    statistics[accu]["death"] += 1
                elif life:
                    statistics[accu]["life"] += 1
                else:
                    if statistics[accu].has_key(last):
                        statistics[accu][last] += 1
                    else:
                        statistics[accu][last] = 1
                #endif
            #endif
        #end for
        if index % 100 == 0:
            print "  Processed about " + str(index) + " lines."
        #if index == 10000:
        #    break
    #end for
#end with
#output
print "\nProcessing ended. Start Outputing...\n"
fo = open("output.txt", "w")
fo.write("----OUTPUT----\n\n")
#fo.write(str(statistics))
for accu, info in statistics.items():
    fo.write(accu)
    fo.write("\n")
    fo.write("刑期 " + "数量")
    fo.write("\n")
    for key, val in info.items():
        fo.write(str(key))
        fo.write(" : ")
        fo.write(str(val))
        fo.write("\n")
    #end for
    fo.write("\n")
#end for
fo.write("\n----OUTPUT ENDED----\n")

注意事项&备注

字符编码

控制台输入的中文罪名字符串会被以16进制的数字存放,而读入文件中的中文字符串是utf-8格式,直接比较二者是不相等的!因此需要在输入阶段利用mystr = unicode(mystr, 'utf-8')将输入的mystr编码为utf-8格式。

打开文件

Python中的with expression [as target]:语句为异常处理提供了支持。target会接收expression返回的结果。with中的代码块如果出现异常便会exit。利用with open([file], [mode]) as f打开的文件不需要close释放资源,with结束时会自动释放。
for line in f会遍历文件的每一行

Json解析

遍历文件每一行后,得到了名为line的字符串。利用json.loads(line)将字符串还原为dictionary格式。

dictionary

访问方式:用dict[key]取value值。
本例中一个案件可能对应多项罪名,因此罪名是以list的数据格式存放的,因此需要遍历每个罪名:for accu in dict_meta["accusation"]
dictionary中提供has_key(key)的方法,返回bool类型,用于查找是否存在key。
dict[key] = new_value语句将会更新key对应的value值。如果key不存在,将会创建这个key并赋值为new_value
遍历dictionary的方式有两种:

for key, value in dict.items():    #items返回一对key和value,并将它们分别赋值给key, value
    ...
for it in dict.items():    #items返回一对,it是包含这对key和value的“一个数据”
    ...

文件写入

"w"模式打开文件后,用write(string)方法。注意write()中只能填一个string,末尾不会输出换行。

Python3

以上程序是Python2版本下的。Python2在字符串的编码问题上甚是烦人,因此采用Python3可以避免不必要的麻烦。Python3读入的字符串不需要特意编码便可以比对。于是可以将程序进行少许修改升级为Python3版本:
输入部分只需要写:

mystr = input("  input No." + str(i) + " : ")

Python3没有raw_input,直接input就可以实现将不用输入引号的中文读取为字符串。
Python3中dictionary没有has_key()方法,而是用in代替。将上述程序中所有的has_key()查询语句改为:

if [the_key_to_find] in [dict]

形式即可。

GitHub链接

PyCharm工程文件已放置GitHub:
Co1lin/Computational-Social-Science-Course/cail
README.md处有Python3版本的链接。
数据集来源:
thunlp/cail

Last modification:May 2nd, 2020 at 01:09 am
如果觉得我的文章对你有用,请随意赞赏