使用Python检测文章抄袭及去重算法原理解析


Posted in Python onJune 14, 2019

在互联网出现之前,“抄”很不方便,一是“源”少,而是发布渠道少;而在互联网出现之后,“抄”变得很简单,铺天盖地的“源”源源不断,发布渠道也数不胜数,博客论坛甚至是自建网站,而爬虫还可以让“抄”完全自动化不费劲。这就导致了互联网上的“文章”重复性很高。这里的“文章”只新闻、博客等文字占据绝大部分内容的网页。

使用Python检测文章抄袭及去重算法原理解析

中文新闻网站的“转载”(其实就是抄)现象非常严重,这种“转载”几乎是全文照抄,或改下标题,或是改下编辑姓名,或是文字个别字修改。所以,对新闻网页的去重很有必要。

一、去重算法原理

文章去重(或叫网页去重)是根据文章(或网页)的文字内容来判断多个文章之间是否重复。这是爬虫爬取大量的文本行网页(新闻网页、博客网页等)后要进行的非常重要的一项操作,也是搜索引擎非常关心的一个问题。搜索引擎中抓取的网页是海量的,海量文本的去重算法也出现了很多,比如minihash, simhash等等。

在工程实践中,对simhash使用了很长一段时间,有些缺点,一是算法比较复杂、效率较差;二是准确率一般。

网上也流传着百度采用的一种方法,用文章最长句子的hash值作为文章的标识,hash相同的文章(网页)就认为其内容一样,是重复的文章(网页)。

这个所谓的“百度算法”对工程很友好,但是实际中还是会有很多问题。中文网页的一大特点就是“天下文章一大抄”,各种博文、新闻几乎一字不改或稍作修改就被网站发表了。这个特点,很适合这个“百度算法”。但是,实际中个别字的修改,会导致被转载的最长的那句话不一样,从而其hash值也不一样了,最终结果是,准确率很高,召回率较低。

为了解决这个问题,我提出了nshash(top-n longest sentences hash)算法,即:取文章的最长n句话(实践下来,n=5效果不错)分别做hash值,这n个hash值作为文章的指纹,就像是人的5个手指的指纹,每个指纹都可以唯一确认文章的唯一性。这是对“百度算法”的延伸,准确率还是很高,但是召回率大大提高,原先一个指纹来确定,现在有n个指纹来招回了。

二、算法实现

该算法的原理简单,实现起来也不难。比较复杂一点的是对于一篇文章(网页)返回一个similar_id,只要该ID相同则文章相似,通过groupby similar_id即可达到去重目的。

为了记录文章指纹和similar_id的关系,我们需要一个key-value数据库,本算法实现了内存和硬盘两种key-value数据库类来记录这种关系:

HashDBLeveldb 类:基于leveldb实现, 可用于海量文本的去重;

HashDBMemory 类:基于Python的dict实现,可用于中等数量(只要Python的dict不报内存错误)的文本去重。

这两个类都具有get()和put()两个方法,如果你想用Redis或MySQL等其它数据库来实现HashDB,可以参照这两个类的实现进行实现。

使用Python检测文章抄袭及去重算法原理解析

使用Python检测文章抄袭及去重算法原理解析

HashDBLeveldb类的实现

使用Python检测文章抄袭及去重算法原理解析

使用Python检测文章抄袭及去重算法原理解析

HashDBMemory类的实现

从效率上看,肯定是HashDBMemory速度更快。利用nshash对17400篇新闻网页内容的测试结果如下:

HashDBLeveldb: 耗时2.47秒; HashDBMemory: 耗时1.6秒;

具体测试代码请看 example/test.py。

有了这两个类,就可以实现nshash的核心算法了。

首先,对文本进行分句,以句号、感叹号、问号、换行符作为句子的结尾标识,一个正在表达式就可以分好句了。

其次,挑选最长的n句话,分别进行hash计算。hash函数可以用Python自带模块hashlib中的md5, sha等等,也可以用我在爬虫教程中多次提到的farmhash。

最后,我们需要根据这n个hash值给文本内容一个similar_id,通过上面两种HashDB的类的任意一种都可以比较容易实现。其原理就是,similar_id从0开始,从HashDB中查找这n个hash值是否有对应的similar_id,如果有就返回这个对应的similar_id;如果没有,就让当前similar_id加1作为这n个hash值对应的similar_id,将这种对应关系存入HashDB,并返回该similar_id即可。

这个算法实现为NSHash类:

使用Python检测文章抄袭及去重算法原理解析

使用Python检测文章抄袭及去重算法原理解析

NSHash类的实现

三、使用方法 

import nshash
nsh = nshash.NSHash(name='test', hashfunc='farmhash', hashdb='memory')
similar_id = nsh.get_similar(doc_text)

NSHash 类有三个参数:

  • name : 用于hashdb保存到硬盘的文件名,如果hashdb是HashDBMemory, 则用pickle序列化到硬盘;如果是HashDBLeveldb,则leveldb目录名为:name+'.hashdb'。name按需随便起即可。
  • hashfunc : 计算hash值的具体函数类别,目前实现两种类型: md5 和 farmhash 。默认是 md5 ,方便Windows上安装farmhash不方便。
  • hashdb :默认是 memory 即选择HashDBMemory,否则是HashDBLeveldb。

至于如何利用similar_id进行海量文本的去重,这要结合你如何存储、索引这些海量文本。可参考 example/test.py 文件。这个test是对excel中保存的新闻网页进行去重的例子。

总结

以上所述是小编给大家介绍的使用Python检测文章抄袭及去重算法原理解析 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
玩转python爬虫之URLError异常处理
Feb 17 Python
Python用UUID库生成唯一ID的方法示例
Dec 15 Python
python 基本数据类型占用内存空间大小的实例
Jun 12 Python
Python 一句话生成字母表的方法
Jan 02 Python
pyqt5与matplotlib的完美结合实例
Jun 21 Python
Pytorch 中retain_graph的用法详解
Jan 07 Python
Python使用qrcode二维码库生成二维码方法详解
Feb 17 Python
python函数enumerate,operator和Counter使用技巧实例小结
Feb 22 Python
python的Jenkins接口调用方式
May 12 Python
Python logging模块写入中文出现乱码
May 21 Python
利用python控制Autocad:pyautocad方式
Jun 01 Python
pytorch下的unsqueeze和squeeze的用法说明
Feb 06 Python
Ubuntu下Anaconda和Pycharm配置方法详解
Jun 14 #Python
PyQt5 加载图片和文本文件的实例
Jun 14 #Python
pyqt5 使用label控件实时显示时间的实例
Jun 14 #Python
ubuntu 18.04搭建python环境(pycharm+anaconda)
Jun 14 #Python
pyqt5 comboBox获得下标、文本和事件选中函数的方法
Jun 14 #Python
PyQt4实时显示文本内容GUI的示例
Jun 14 #Python
详解Python 定时框架 Apscheduler原理及安装过程
Jun 14 #Python
You might like
php批量缩放图片的代码[ini参数控制]
2011/02/11 PHP
PHP递归算法的详细示例分析
2013/02/19 PHP
php获取网站百度快照日期的方法
2015/07/29 PHP
[原创]ThinkPHP中SHOW_RUN_TIME不能正常显示运行时间的解决方法
2015/10/10 PHP
PHP的Yii框架中移除组件所绑定的行为的方法
2016/03/18 PHP
php使用fputcsv实现大数据的导出操作详解
2020/02/27 PHP
tp5.1 框架路由操作-URL生成实例分析
2020/05/26 PHP
PHP数组Key强制类型转换实现原理解析
2020/09/01 PHP
JavaScript中的细节分析
2012/06/30 Javascript
Javascript图像处理—为矩阵添加常用方法
2012/12/27 Javascript
原生js拖拽(第一课 未兼容)拖拽思路
2013/03/29 Javascript
图片轮换效果实现代码(点击按钮停止执行)
2013/04/12 Javascript
form.submit()不能提交表单的原因分析
2014/10/23 Javascript
jQuery ajax serialize() 方法使用示例
2014/11/02 Javascript
jquery插件bxslider用法实例分析
2015/04/16 Javascript
jQuery实现带滚动导航效果的全屏滚动相册实例
2015/06/19 Javascript
JS获取IMG图片高宽的简单实例
2016/05/17 Javascript
Bootstrap select多选下拉框实现代码
2016/12/23 Javascript
关于JS Lodop打印插件打印Bootstrap样式错乱问题的解决方案
2016/12/23 Javascript
AngularJS 限定$scope的范围实例详解
2017/06/23 Javascript
微信小程序scroll-view横向滑动嵌套for循环的示例代码
2018/09/20 Javascript
vue实现移动端项目多行文本溢出省略
2020/07/29 Javascript
[01:16:13]DOTA2-DPC中国联赛 正赛 SAG vs Dragon BO3 第一场 2月22日
2021/03/11 DOTA
Python采用Django开发自己的博客系统
2020/09/29 Python
python使用xslt提取网页数据的方法
2018/02/23 Python
Python文本处理之按行处理大文件的方法
2018/04/09 Python
Python模块的定义,模块的导入,__name__用法实例分析
2020/01/07 Python
几个CSS3的flex弹性盒模型布局的简单例子演示
2016/05/12 HTML / CSS
HTML5 History API 实现无刷新跳转
2016/01/11 HTML / CSS
中科前程Java笔试题
2016/11/20 面试题
集团公司总经理岗位职责
2013/12/20 职场文书
市级绿色学校申报材料
2014/08/25 职场文书
民主评议政风行风整改方案
2014/09/17 职场文书
党员批评与自我批评发言
2014/10/02 职场文书
2015年财务个人工作总结范文
2015/05/22 职场文书
Python中OpenCV实现简单车牌字符切割
2021/06/11 Python