Python法律实务——利用批量裁判文书内容制作行业白皮书(也可用于诉讼可视化实践)

网友投稿 734 2022-05-29

前面的文章介绍了裁判文书中数据信息的提取,裁判文书目前作为学术研究、案件指引最重要的大数据源,受到了越来越多的重视。在实际工作中,许多律所或者律师,出于学术研究、业务宣传、品牌宣传等目的,会在自己的公号或者私有媒体对一些行业案件进行归纳整理分析。根据这些数据的指引,我们不仅能了解到学习法律知识,同样可以参照来作为案件的办理指引。

接下来,笔者就以帮助专做劳动法的同事陈律师制作某个行业白皮书(餐饮行业的劳动法领域)的过程为例,来做深入的介绍。

实践难度 :高

知识点涉及:正则表达式、python-docx库处理docx文档、pandas库处理excel文档、文件夹的遍历、Pyecharts制作图表

面向对象:掌握了Python初、中级别知识,熟悉了Python上述几个模块的基本使用方法的读者。

第一步 数据准备

由于绝大部分读者,不具备自建裁判文书数据库的能力,所以需要提前到裁判文书、或者类似网站进行检索,将检索到的裁判文书进行批量下载。

笔者当然是有自己的数据库的,但是为了演示,这里下载了2019年100多份相关的裁判文书。

第二步 设计编程思路

设计正则表达式,从文书中提取仲裁的请求

Python法律实务——利用批量裁判文书内容制作行业白皮书(也可用于诉讼可视化实践)

遍历所有docx文档,再利用python-docx库遍历文档中的每一段进行正则匹配

将匹配结果导出excel表格中

处理和分析excel表格

将excel表格数据转化为可视化图表

第三步 编程与调试

pattern=".*?申请仲裁.{1,5}[请要]求" _re =re.compile(pattern,re.M|re.S|re.I) result=[] unmatched=[] files=[] for parent, dirnames, filenames in os.walk(r'餐饮大数据分析', followlinks=True): for filename in filenames: file_path = os.path.join(parent, filename) if '.docx' in file_path: _i={'fileName':filename,'filePath':file_path} files.append(_i) print(files) print('files length:',len(files))

正则表达式

为了提取到我们的目标段落,我们先要找一个样本出来:

我们需要从判决书中找出双方的仲裁请求的那一段,并提取出来,通过这一段样本,我初步的正则表示为:

pattern=".*?申请仲裁.{1,5}[请要]求"

接下来我们要找出所有的docx文件,这个很简单,之前的文章已经介绍过文件夹的遍历:

files=[] for parent, dirnames, filenames in os.walk(r'餐饮大数据分析', followlinks=True): for filename in filenames: file_path = os.path.join(parent, filename) if '.docx' in file_path: _i={'fileName':filename,'filePath':file_path} files.append(_i) print(files) print('files length:',len(files)) ------------------------------------- [{'fileName': '10-上海广增餐饮管理有限公司与雷楠劳动合同纠纷一审民事判决书.docx', 'filePath': '餐饮大数据分析\\20200523004507\\10-上海广增餐饮管理有限公司与雷楠劳动合同纠纷一审民事判决书.docx'}, {'fileName': '11-宏葡(上海)餐饮有限公司与颜丹丹劳动合同纠纷一审民事判决书.docx', 'filePath': '餐饮大数据分析\\20200523004507\\11-宏葡(上海)餐饮有限公司与颜丹丹劳动合同纠纷一审民事判决书.docx'} …………] files length: 117

接下来,我们需要遍历每一个word文件,并将word文档按照段落进行匹配:

pattern=".*?申请仲裁.{1,5}[请要]求" _re =re.compile(pattern,re.M|re.S|re.I) result=[] unmatched=[] files=[] for parent, dirnames, filenames in os.walk(r'餐饮大数据分析', followlinks=True): # dirnames 子文件夹 for filename in filenames: file_path = os.path.join(parent, filename) if '.docx' in file_path: _i={'fileName':filename,'filePath':file_path} files.append(_i) for i in files: document = Document(i['filePath']) sig=0 for paragraph in document.paragraphs: res=_re.search(paragraph.text) if res is not None: _o={'fileName':i['fileName'],'filePath':i['filePath'],'paragraph':paragraph.text} result.append(_o) sig=1 break #匹配一次后,后面的段落就不再匹配 if sig==0: _o = {'fileName': i['fileName'], 'filePath': i['filePath']} unmatched.append(_o) print('result:',result) print('result length:',len(result)) print('unmatched:',unmatched) print('unmatched length:',len(unmatched)) ---------------------------------------- result: [{'fileName': '11-宏葡(上海)餐饮有限公司与颜丹丹劳动合同纠纷一审民事判决书.docx',…………] result length: 61 unmatched: [{'fileName': '10-上海广增餐饮管理有限公司与雷楠劳动合同纠纷一审民事判决书.docx', ……] unmatched length: 56

_re =re.compile(pattern,re.M|re.S|re.I)

由于同一个正则表达式要多次重复使用,为了提升匹配效率,可以使用re.compile()来编译正则表达式,生成一个正则表达式对象,从而提升效率。

document = Document(i['filePath'])

先实例化一个docx对象

for paragraph in document.paragraphs

依次遍历这个docx对象中所有的段落

我们将匹配到的结果放入到result这个别表中,没匹配到的放到unmatched中,上面的结果可以看到result的长度只有61个,说明只匹配到了61个文档,显然这个正则表达式,匹配成功率不高。

为了作进一步处理,以及复查数据,我们将结果存储为excel表格:

data={'段落':[],'文件名称':[],'文件相对路径':[]} unmatched_data={'文件名称':[],'文件相对路径':[]} for p in result: data['段落'].append(p['paragraph']) data['文件名称'].append(p['fileName']) data['文件相对路径'].append(p['filePath']) for q in unmatched: unmatched_data['文件名称'].append(q['fileName']) unmatched_data['文件相对路径'].append(q['filePath']) df = pd.DataFrame(data) df.to_csv('result.csv', index=True,encoding="utf_8_sig") df = pd.DataFrame(unmatched_data) df.to_csv('noresult.csv', index=True,encoding="utf_8_sig")

通过上述代码,我们就将匹配到的结果列表result和未匹配到的结果列表unmatched,保存为名为"result.csv"和"noresult.csv"的两个表格。当然也可以将这两个数据合并到一个excel表格里。通过没匹配到的列表中的word文档查看,进一步修改了正则表达式:

pattern=".*?(?:申请|提起).*?(?:仲裁|申诉)"

以这种方式匹配出来104个,还有13个没有匹配到,这个时候,再去完善正则意义似乎不太大,毕竟只剩13个,人工匹配一下段落也很快。

result.csv表格内容截图:

到这一步,我们已经把所有的文书,都提取了我们想要的段落,并进行了保存。

我们下一步,需要提取段落中的争议重点,这一步并非不是不能通过Python处理,只是难度和前期时间成本非常大,这里我建议暂时通过人工的方式处理。在精选的字段中提取关键信息,由于已经给人工处理排除掉了许多无关信息,时间成本尚可接受。

笔者在上述表格的E列增加一个字段“案件焦点”,当然增加到其他列也可以,然后陈律师让助理在该列依次填入了归纳的焦点。

第四步 数据可视化展现

这里数据可视化,一样要用到pandas库来处理csv文件,同时也会利用到pyecharts模块,

读取csv文件,做先行处理:

import pandas df=pd.read_csv('result.csv') result={} for index, row in df.iterrows(): key=row[4] if key not in result: result[key]=1 else: result[key]+=1 print('result:',result) --------------------------------------------- result={'支付工资_无需支付工资': 38, '加班工资': 28, '赔偿金': 31, '补偿金': 1, '补贴': 1,'返还设备':1, '返还私自承接业务的收益_提成':2, '工资差额_加班工资差额':39,'工作垫付款_预付款':3,'工伤认定':2,'经济损失':2 ,'应休未休年休假折算工资':10,'刑事判决书':7,'押金':1,'一次性工伤、伤残补助金、医疗费':3}

转换为pyecharts要求的参数的数据格式:

_list=[] for k in result: p=(k,result[k]) _list.append(p) print(_list) ------------------------------- [('支付工资_无需支付工资', 38), ('加班工资', 28), ('赔偿金', 31), ('补偿金', 1), ('补贴', 1), ('返还设备', 1), ('返还私自承接业务的收益_提成', 2), ('工资差额_加班工资差额', 39), ('工作垫付款_预付款', 3), ('工伤认定', 2), ('经济损失', 2), ('应休未休年休假折算工资', 10), ('刑事判决书', 7), ('押金', 1), ('一次性工伤、伤残补助金、医疗费', 3)]

转换为图表

pie = Pie() pie.add("", _list) pie.set_global_opts(title_opts=opts.TitleOpts(title="Pie-争议点分布"),legend_opts=opts.LegendOpts(is_show = False)) pie.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}")) pie.render("pie.html")

转换为饼图:

我们也可以根据需要,转换为其他的柱状图、折线图等等其他图表。这里不做更多介绍。

总结

本文涉及的知识点比较多,难点主要在于正则表达式的书写,需要尽可能多的满足大部分文档的要求,否则剩余的文档越多,手工处理的工作会越多,正则表达式的书写,需要反复查询未匹配到的文档,进行修正。

其他的知识点,还涉及到文件夹文件遍历和筛选、word文档处理、excel文档处理,数据可视化操作等知识点,但总体而言,处理的方式还是中规中矩的,前面的文章也全都介绍过。

另外,我们也发现,Python并不能代替所有工作,争议点的筛查提取,还是需要人工来处理。不过实际上,通过机器学习等技术,也是完全可以实现自动化的。但是对于普通使用者来说,学习门槛和时间成本都太高,得不偿失。得益于前期的段落提取,这一步的工作量相对已经简单了很多。另外,本文呈现的最终结果,也并不完美,要得到更完美的报告,还需要不少润色和处理。

从另一个视角来看,本文的方法不仅可以用来做行业的白皮书,也可以用于诉讼领域,将类案查询结果,利用Python数据处理分析后,转化为可视化图表,会得到更好的庭审展示效果。

Python 大数据

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:同样是断言,为何 Hamcrest 如此优秀?
下一篇:【产品】禅道项目管理简析
相关文章