一个简单的python代码剽窃检测工具

pycode-similar的Python项目详细描述


这是一个简单的python代码剽窃检测工具,其基本思想是规范python ast表示,并使用difflib获取从引用代码到候选代码的修改。pycode_similar中定义的剽窃是指候选代码剽窃了多少引用代码,这意味着交换引用代码和候选代码会得到不同的结果。

我只花了几个小时就实现了这个工具,所以要提高速度和准确性还有很长的路要走,但是它已经在检测我们公司新兵的家庭作业抄袭方面表现出色。

与苔藓相比

  • 纯python实现
  • 仅包含一个源文件
  • 没有第三方依赖关系(使用treediff时zss除外)
  • 无需注册moss账户
  • 无需网络即可访问MOSS

这个工具在我知道有一个Moss (for a Measure Of Software Similarity)来确定程序的相似性之前就诞生了。我尝试了很多方法来注册斯坦福莫斯的账户,但仍然无法获得有效的账户。所以,我无法准确地比较pycode_similar和moss。

安装

如果时间不多,只需执行

$ pip install pycode_similar

它将在您的系统上安装模块(无需测试)。

另外,您可以复制并粘贴不需要第三方依赖的pycode_similar.py。

用法

如果pip安装正确,只需将其用作标准命令行工具。

$ pycode_similar
usage: pycode_similar [-h] [-l L] [-p P] files files

A simple plagiarism detection tool for python code

positional arguments:
  files       the input files

optional arguments:
  -h, --help  show this help message and exit
  -l L        if AST line of the function >= value then output detail
              (default: 4)
  -p P        if plagiarism percentage of the function >= value then output
              detail (default: 0.5)

pycode_similar: error: too few arguments

当然,您也可以将其用作python库。

importpycode_similarpycode_similar.detect([referenced_code_str,candidate_code_str1,candidate_code_str2,...],diff_method=UnifiedDiff)

实施

该工具实现了两种diff方法:基于行的diff(unifieddiff)和基于树编辑距离的diff(treediff),这两种方法都在函数ast级运行。

  • unifieddiff,diff规范化函数ast字符串行,简单但高效。
  • treediff,diff函数ast,速度很慢,对小函数效果不好。(取决于zss

所以,在cmd中运行这个工具时,默认的diff方法是unifieddiff。当你把它用作图书馆时,你可以切换到treediff。

测试

如果您有源代码,则可以使用

$ python pycode_similar/tests/test_cases.py

或执行

$ python pycode_similar.py pycode_similar/tests/original_version.py pycode_similar.py

ref: tests/original_version.py
candidate: pycode_similar.py
80.14 % (803/1002) of ref code structure is plagiarized by candidate.
candidate function plagiarism details (AST lines >= 4 and plagiarism percentage >= 0.5):
1.0 : ref FuncNodeCollector._mark_docstring_sub_nodes<24:4>, candidate FuncNodeCollector._mark_docstring_sub_nodes<27:4>
1.0 : ref FuncNodeCollector._mark_docstring_nodes<54:8>, candidate FuncNodeCollector._mark_docstring_nodes<57:8>
1.0 : ref FuncNodeCollector.generic_visit<69:4>, candidate FuncNodeCollector.generic_visit<72:4>
1.0 : ref FuncNodeCollector.visit_Str<74:4>, candidate FuncNodeCollector.visit_Str<78:4>
1.0 : ref FuncNodeCollector.visit_Name<83:4>, candidate FuncNodeCollector.visit_Name<88:4>
1.0 : ref FuncNodeCollector.visit_Attribute<89:4>, candidate FuncNodeCollector.visit_Name<88:4>
1.0 : ref FuncNodeCollector.visit_ClassDef<95:4>, candidate FuncNodeCollector.visit_ClassDef<100:4>
1.0 : ref FuncNodeCollector.visit_FunctionDef<101:4>, candidate FuncNodeCollector.visit_FunctionDef<106:4>
1.0 : ref FuncInfo.__init__<141:4>, candidate FuncInfo.__init__<161:4>
1.0 : ref FuncInfo.__str__<151:4>, candidate FuncInfo.__str__<171:4>
1.0 : ref FuncInfo.func_code<162:4>, candidate FuncInfo.func_code<182:4>
1.0 : ref FuncInfo.func_code_lines<168:4>, candidate FuncInfo.func_code_lines<188:4>
1.0 : ref FuncInfo.func_ast<174:4>, candidate FuncInfo.func_ast<194:4>
1.0 : ref FuncInfo.func_ast_lines<180:4>, candidate FuncInfo.func_ast_lines<200:4>
1.0 : ref FuncInfo._retrieve_func_code_lines<186:4>, candidate FuncInfo._retrieve_func_code_lines<206:4>
1.0 : ref FuncInfo._iter_node<208:4>, candidate FuncInfo._iter_node<228:4>
1.0 : ref FuncInfo._dump<232:4>, candidate FuncInfo._dump<252:4>
1.0 : ref FuncInfo._inner_dump<242:8>, candidate FuncInfo._inner_dump<262:8>
1.0 : ref ArgParser.error<267:4>, candidate ArgParser.error<291:4>
0.95: ref unified_diff<281:0>, candidate UnifiedDiff._gen<339:8>
0.92: ref FuncNodeCollector.__init__<18:4>, candidate FuncNodeCollector.__init__<20:4>
0.92: ref FuncNodeCollector.visit_Compare<108:4>, candidate FuncNodeCollector._simple_nomalize<117:8>
0.89: ref FuncNodeCollector.visit_Expr<79:4>, candidate FuncNodeCollector.visit_Expr<83:4>

单击here 若要查看此差异->;0.92:ref funcnodecollector。请访问候选funcnodecollector的“比较”<;108:4>;。\u简单的“正常化”<;117:8>;

存储库

该项目托管在github上。您可以在此处查看源代码:

https://github.com/fyrestone/pycode_similar

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Jetty是否有请求缓存?   数组中的java 2值与我的数据帧中的2列对应   对象序列化期间的java DbUtils类型转换问题   java根面板中不显示所有单独的面板   java通过代理或SSH隧道连接Hbase API   java困惑:与经典MVC控制器相比,JSF2中bean的角色   java在我的Triangle类中“找不到符号错误”   java在Android中设置从路径到自定义按钮的图像   java不绕轨道旋转椭圆   AES在socket上搞砸了序列化/反序列化。无效的流标头。JAVA   java在数组中搜索term和if语句   线程“main”java中出现异常。util。正则表达式。PatternSyntaxException:在索引0附近悬挂元字符“*”*   Websphere上的java Google反射无法打开url连接   java为什么inc/dec频道什么都不做?   java KeyListener无法访问keyPressed方法