APP下载

Python技术在围标和串标审计项目中的应用
——提升审计效率的Python技术应用

2023-07-17吴大进

中国新技术新产品 2023年8期
关键词:串标围标词频

吴大进

(安徽宝申会计师事务所,安徽 合肥 230001)

0 引言

围标和串标是招投标过程中比较典型的一类违法违规行为,严重扰乱了正常市场秩序,直接伤害了发标人和其他投标人的合法权益,也给投标项目质量和安全带来严重的风险隐患,查处围标和串标行为一直是审计的重点内容。传统的审计思路是核对MAC 地址是否一致、IP 地址是否一致、工程造价软件锁编码是否一致以及投标保证金缴付账号是否一致。根据《中华人民共和国招标投标法实施条例》第40 条规定发现上述情形之一的,视为投标人相互串通投标。

目前,围标和串标行为也随之发生了新变化,为逃避法律法规监管,围标和串标行为越来越隐蔽,越来越职业化。围标人一般会联系多家投标人对某个重大项目进行重点投标,由围标人团队统一制作各家标书,陪标人负责提供复印件、签字、盖章、缴付投标保证金、上传标书等事项。这种围标和串标方式隐蔽性强,一般很难通过MAC 地址、IP 地址、工程造价软件锁编码和投标保证金账号一致等途径发现审计证据,如何发现重大项目中围标和串标行为已经成为摆在审计人员面前亟待解决的重要难题。

1 审计思路

围标人团队统一编写各家标书时会刻意避免雷同文本出现,但是语言风格、表达习惯、词汇特征等语言表达特点不会发生本质变化,因此投标文件异常一致或高度雷同是重点审计方向。投标文件响应招标文件,部分内容雷同属于正常情况,但不同投标人技术标中个性化内容不可能完全相同,即使部分技术参数指标基本相同(如技术方案、产品技术参数和实施计划等),但落实到纸面上的文字也不会完全相同,因此不同投标人制作的标书内容会有差异。如果2 份投标文件使用词汇、出现频次、生僻词、错别字高度一致,则存在由同一个人或同一团队编写的重大嫌疑[1]。

传统的审计方法是人工比对、分析招投标文件,查找围标和串标线索,如技术标中方案细节一致、投标文件中瑕疵或错别字一致和大段内容重复雷同等。通常每份投标文件都在几万字左右,大型投标项目一般都有几十家甚至上百家投标企业,人工梳理如同大海捞针,难以全面处理大批量文该文件。而利用Python 的分词技术、字典容器和矩阵演算等方法,可以用少量基础代码构建算法模型,帮助审计人员高效地完成投标文件词频统计、集合运算和结构化分析、扫描投标文件,为复杂的审计项目提供技术支持。

算法模型:设置文本词组重合比例和重复比例2 份阈值来判断2 份投标文件的相似程度,如果2 份投标文件的相似度超过一定阈值,则2 份投标文件存在由同一个人或同一团队编写的重大嫌疑。

阈值1:词组重合比例,即2 份文本中共同使用的词组数量占2 份文本全部使用词组数量的比例,每个词组只计数一次[2]。

阈值2:词组重复比例,即2 份文本中重复出现的词组数量占2 份文本总词组数量的比例,每个词组按出现频次计数。

由于汉字的使用习惯,不同文本之间都会存在词组重合基数,根据收集的500 份1.5 万~3 万字不同类型文该文件(包括小说、通信稿件、审计报告、产品说明书、投标文件、游戏攻略和电影剧本等)的分析结果,不同类型文本之间词组重合比例在11%~24%,词组重复比例在13%~30%。投标文件响应招标文件部分内容雷同,同一项目投标文件词组重合比例和词组重复比例较高属于正常现象。2021 年某省公共资源交易中心围标和串标审计项目经公安机关协调筛选了17 个完全没有围标和串标嫌疑的项目,取得838 份投标文件电子版,经过分析比对同一项目投标文件的词组重合比例在28%~43%,词组重复比例在31%~52%。

综上所述,将2 份投标文件词组重合比例阈值设定为70%和词组重复比例阈值设定为75%,如果词组重合比例和词组重复比例都超过了阈值,则2 份投标文件高度相似,存在围标和串标的重大嫌疑。进一步通过“词频分析结果”Excel 文件梳理关键词组(生僻词、错别字等)出现频次是否高度一致,固定审计证据,锁定涉嫌围标和串标的投标文件。

2 程序代码语句

基于Python 编写的算法模型由主程序和4 个可调用的自定义函数构成。

2.1 主程序

第一步,导入需要使用的模块,包括jieba(用于中文分词)、docx(用于读取word 文档)、Counter(用于计算词频)和xlwings(用于Excel 数据输出)。第二步,连续2 次调用自定义函数1,即def group_dict(file),对2 个指定的word 文档进行分词,并将每个词组出现的次数记录在字典中。第三步,调用自定义函数2,即def coincide(dict1,dict2),比较2 个文档的词组,找出重复的词组,并将重复的词组及其出现次数记录在另一个字典中。第四步,调用自定义函数3,即def analyse(dict1,dict2,dict3),根据以上统计结果,输出2 个文档的词组数量、重复词组数量及比例等信息。第五步,使用print()语句将文档的词组数量、重复词组数量及比例等信息打印在屏幕上,实际运行效果如图1 所示。第六步,调用自定义函数4,即def output(dict1,dict2),将词组及其出现次数分别输出到Excel 文件中。

图1 主程序在Python 解释器中实际运行效果

主程序代码如下。

import jieba # 导入jieba 模块

from docx import Document # 导入Document模块,用于读取word 文档

from collections import Counter # 导入Counter 模块,用于计算词频

mport xlwings as xw # 导入xlwings 模块

file1 = "C:/Users/86139Desktop/比对文本/20210104投标文件1.docx"file2 ="C:/Users/86139Desktop/比对文本/20210104 投标文件2.docx"

word_dict1=group_dict(file1) #调用自定义函数1

word_dict2=group_dict(file2) #调用自定义函数1

word_dict3=coincide(word_dict1,word_dict2) #调用自定义函数2

n1,n2,n3,n4,n5=analyse(word_dict1,word_dict2,word_dict3)#调用自定义函数3

results1=f'投标文件1 使用词组{len(word_dict1)}个,投标文件2 使用词组{len(word_dict2)}个,二个文件使用词组重合{n1}个,词组重合比例{n2}%'

results2=f'投标文件1 词组合计{sum(word_dict1.values())}个,投标文件2 词组合计{sum(word_dict2.values())}个,

二个文件使用重复词组合计{n4}个,词组重复比例{n5}%'

print(results1)

print(results2)

output(word_dict1,word_dict2) #调用自定义函数4

2.2 自定义函数1:def group_dict(file)

第一步,使用Document 函数读取word 文档。第二步,使用for paragraph in document.paragraphs 语句遍历文档的每段,调用jieba.lcut(paragraph.text)方法进行分词,for 循环将每个词组添加到word_list 列表中。第三步,使用Counter 函数统计每个词出现的次数,并使用del word_dict[key]方法删除字典中的标点符号、特殊字符、换行符和空格等干扰信息。第四步,使用sorted(word_dict.items(), key=lambda x:x[1], reverse=True)方法按照词频降序排序,返回排序后的“词频字典”return word_dict。

Python 中的字典是一种特殊的数据结构,它是一种键值对的集合,每个键都与一个值相关联。字典的特点是其中的键是唯一的,值可以是任何类型,可以使用键来访问值[3]。

自定义函数1 程序代码如下。

def group_dict(file):

document = Document(file)

word_list = []

for paragraph in document.paragraphs:words = jieba.lcut(paragraph.text)for word in words:

word_list.append(word)word_dict = Counter(word_list)for key in list(word_dict.keys()):

del word_dict[key]

if key in '是的和与在等为对中年月日吗':del word_dict[key]

if key=='':

del word_dict[key]

word_dict_sort = sorted(word_dict.items(), key=lambda x:x[1], reverse=True)

word_dict=dict(word_dict_sort)return word_dict

2.3 自定义函数2:def coincide(dict1,dict2)

第一步,以dict3t = {}创建一个新字典。第二步,for key in dict 循环遍历投标文件“词频字典”dict1 和dict2,使用if key in dict2 判断语句,如果2 个字典中有相同的键,使用min(dict1[key], dict2[key])方法将交集的键和较小的键值添加到新字典dict3 中。第三步,返回“重复词组词频字典”return dict3。

自定义函数2 程序代码如下。

def coincide(dict1,dict2):dict3t = {}

1.2.3 Transwell实验检测细胞迁移和侵袭能力 收集1.2.1稳定表达miR-145SiHa细胞,无血清培养基制细胞悬液,接种于Transwell小室上层(3×103个/孔)[6]。Transwell小室风干后,加入500 μL 0.1%结晶紫染色,显微镜下拍照并计数发生迁移的细胞数量。细胞侵袭实验在Transwell小室上层加入50 μL 2.0 mg/mL基质胶Matrigel,凝固后接种SiHa细胞,之后同细胞迁移操作。

for key in dict1:

if key in dict2:

dict3 [key] = min(dict1[key], dict2[key])return dict3

2.4 自定义函数3:def analyse(dict1,dict2,dict3)

第一步,使用for word in dict 语句分别遍历dict1、 dict2和dict3 这3 个字典。第二步,分析计算2 份投标文件词组重合比例n2 和重复比例n5 来判断2 份文件的相似程度。第三步,返回n1、n2、n3、n4 和n5(词组数量、词组重合比例、总数量、重复词组数量以及词组重复比例),用于主程序print 语句输出程序结果。

词组重合比例n2=dict3 字典键的数量/(dict1 字典键的数量+dict2 字典键的数量-dict3 字典键的数量)。

词组重复比例n5=dict3 字典键值合计/(dict1 字典键值合计+dict2 字典键值合计-dict3 字典键值合计)。

自定义函数3 程序代码如下:

def analyse(dict1,dict2,dict3):n1 = 0

for word in dict1:

if word in dict2:

n1 += 1

n2 = round(n1 / (len(dict1) + len(dict2) - n1)*100,2)

n3 = sum(dict1.values())+sum(dict2.values())

n4 = sum(dict3.values())

n5=round(n4/(n3-n4)*100,2)

return(n1,n2,n3,n4,n5)

2.5 自定义函数4:def output(dict1,dict2)

第一步,使用xlwings 模块xw.Book()和wb.sheets[0]生成一个新的Excel 文件。第二步,利用解包方法for key,value in dict1.items()取得词组重合比例和词组重复比例。第三步,使用sht.range().value 赋值语句将词组重合比例和词组重复比例分析结果分别写入A1 和A2 单元格。第四步,使用sht.range().options(transpose=True).value = list(dict3.keys())语句写入分析过程,A4 单元格纵向写入投标文件1 或文件2 中曾经使用过的全部词组,B4 单元格写入投标文件1 和文件2 中该词组出现总次数,C4 单元格写入投标文件1 该词组出现次数,D4 单元格写入投标文件2该词组出现次数。第五步,以wb.save(“C:/Users/86139/Desktop/词频分析结果.xlsx”)语句将记录上述分析过程的文件保存在桌面并命名“词频分析结果.xlsx”。自定义函数4 程序代码如下。def output(dict1,dict2):

wb = xw.Book()

sht = wb.sheets[0]

sht.range('A1').value = results1

sht.range('A2').value = results2

dict3 = {}

for key, value in dict1.items():if key in dict2:

dict3[key] = value + dict2[key]else:

dict3[key] = value

for key, value in dict2.items():

if key not in dict1:

dict3[key] = value

sht.range('A4').value =“ 词组”

sht.range('A5').options(transpose=True).value = list(dict3.keys())

sht.range('B4').value = '总次数'

sht.range('B5').options(transpose=True).value = list(dict3.values())

sht.range('C4').value = '投标文件1 出现次数'A_list = list(dict3.keys())n=5

for i in range(len(A_list)):

if A_list[i] in dict1.keys():

sht.range('C' + str(n)).value = dict1[A_list[i]]n = n + 1

sht.range('d4').value = '投标文件2 出现次数'A_list = list(dict3.keys())

n = 5

for i in range(len(A_list)):

if A_list[i] in dict2.keys():

sht.range('d' + str(n)).value = dict2[A_list[i]]n = n + 1

wb.save("C:/Users/86139/Desktop/词频分析结果.xlsx")wb.close()

3 实际应用案例

2021 年初某省公共资源交易中心收到举报材料,年初某市重点安置房建设项目中标结果存在围标嫌疑,项目涉案金额巨大,投标人涉及38 家企业,围标手段非常专业,检查MAC 地址、IP 地址、工程造价软件锁编码和投标保证金账号等均未发现异常。仅剩的审计方向就是比对投标文件是否异常一致或高度雷同,如果使用传统的人工方式对38 份投标文件进行比对分析,需要3~4 名审计人员加班加点工作3 周才有可能完成,且而且比对分析效果也很难保证。

审计组运用该文审计技术仅4天时间就完成了全部38份投标文件的相似度分析。一共38 份投标文件,每次比对分析2 份投标文件,共有(38×37)/2=1406 种比对组合,排除反向组合(A-B 组合与B-A 组合是相同的),有效比对组合共计1406/2=703 组。对703 组比对分析结果梳理进行汇总,发现32 份投标文件呈现4 个规律性集合,详见表1。其中,一个集合内元素相似度正常,3 个集合内元素高度相似。集合1 包括6 份投标文件,词组重合比例平均值为35.45%,词组重复比例平均值为38.45%,未超过阈值;集合2 包括12 份投标文件,词组重合比例平均值为77.17%,词组重复比例平均值为81.03%,超过阈值;集合3 包括9 份投标文件,词组重合比例平均值为79.45%,词组重复比例平均值为82.05%,超过阈值;集合4 包括11份投标文件,词组重合比例平均值为74.07%,词组重复比例平均值为79.73%,超过阈值。

表1 38 份投标文件集合分析结果

审计组进一步利用“词频分析结果”Excel 文件重点梳理了38 份投标文件的62 项关键词组(生僻词和错别字等)的出现频率,呈现出高度的一致性和规律性。如“砌筑检查井”,32 份投标文件出现频次在32~35 次,其他投标文件均少于5 次;“工程定位复测”,32 份投标文件均出现8 次,其他投标文件均未出现。“墙角(脚)防潮层”错别字32 份投标文件均出现,其他投标文件均正确,详见表2(关键词频率对比情况)。

表2 关键词组频率对比情况

初步锁定32 家企业涉嫌围标,同举报材料反映的9 家企业涉嫌围标的情况大相径庭。起初公安机关对如此短的时间就反馈审计结果和涉嫌围标企业如此之多也持怀疑态度,后经公安机关侦办核实32 家投标人全部参与该项目串通投标犯罪行为,32 份标书由围标人团队统一通过3 份标书复制、修改、增删制作完成。最终成功破获该起涉及安置房工程招标的特大串通投标案,事半功倍的效率和精准定位的审计手段得到了司法机关的高度评价和专项表彰。

4 小结和前瞻

该文审计方法核心通过Python 技术自动读取文件、中文智能分词、矩阵演算和集合运算,完成了大批量文该文件数据信息要点分割、获取和数据关联性分析,解决了传统方法和人工手段难以全面处理大批量文该文件的难题,未来在判定论文抄袭、快速提取文本关键词、敏感词汇预警等方面都有重要的推广意义。虽然该文审计方法提高了围标和串标审计项目的审计质量和精准度,但是在程序交互性设计和算法模型方面有待进一步完善和提升。

除了上述介绍的Python 技术在围标和串标项目中的审计方法,还有很多基于Python 技术的审计方法值得审计人员不断探索和研究。Python 技术未来在审计项目数据采集清洗、数据挖掘性分析和办公自动化等方面有广泛的应用前景[4]。首先,传统审计范围主要是财务数据,Python技术可以将音视频、图像、定位信息、传感器信息等非结构化信息进行采集、清洗并转换为结构化信息,从而突破传统审计内容的限制,可提供不同维度的大数据,助力于挖掘性分析,推动数据驱动型审计模式的发展[5]。其次,传统审计多数是面对数据和文本的一维界面,很难找出数据中隐藏的规律和问题。Python 技术在数据交互分析、自动化输出以及数据可视化方面都具有无与伦比的优势,包括审计数据以图表、数据矩阵等形式的多维表达,可展示出丰富的细节,为大数据时代创新审计思路、拓宽审计方法提供技术可能性。

5 结语

大数据时代的到来和大数据技术的发展推动了各个行业的转型升级,也给审计人员带来了新的机遇和挑战,“君子性非异也,善假于物也”,审计人员也应与时俱进,主动迎接挑战,创新审计思维,善于运用Python 等大数据技术,将大数据技术与审计业务进行有机融合,努力使自己成长为大数据时代“一专多能”的复合型审计人才,推动审计技术的不断创新。

猜你喜欢

串标围标词频
基于词频分析法的社区公园归属感营建要素研究
企业招投标中的串标问题研究
工程项目招投标串标问题及相关策略分析
词频,一部隐秘的历史
云存储中支持词频和用户喜好的密文模糊检索
以关键词词频法透视《大学图书馆学报》学术研究特色
基于合作博弈视角的工程项目围标现象分析
基于博弈论的串标行为分析及对策探讨
“围标”现象的成因及防范
浅谈工程建设领域围标串标问题的治理