白色衬衫净少年 - 采集框架
type: channel
link: https://bscsjsn.com/tag/%E9%87%87%E9%9B%86%E6%A1%86%E6%9E%B6/
items: 分布式数据采集框架实际工作中的去重是如何实现的-上

分布式数据采集框架实际工作中的去重是如何实现的-上
type: item
date: 2021-10-19T08:33:00+00:00
description: 在我们实际工作中，提到分布式数据采集框架，就不免说起数据去重的问题，对于一个7*24小时不间断的爬虫框架来说，爬虫任务循环往复调度，就必须将数据去重做好，否则就会对同一数据或相似数据进行多次抓取，造成系统资源的浪费，且可能给用户推送N条相同或相似的资讯，致使用户体验感差等问题。本文主要介绍大数据文本去重的方法实现及流程，本人水平有限，如贴中哪里有问题，欢迎批评指正。 资讯抓取的采集系统中，大数据文本去重的过程大致如下： 1.redis对抓取资讯的链接进行过滤性去重 2.simhash去重 redis对链接URL过滤性去重 上面我们提到，分布式数据采集框架一般都是7*24小时不间断抓取的，我们只需要对任务进行抓取配置，例如：任务名称、任务描述、任务优先级、是否重复抓取、抓取间隔、下载路由、重抓次数等，然后上传站点初始url文件及配置等文件，框架就会自动调度、分发任务 那么，问题来了。假设站点A有一篇资讯-分布式及数据同步链接为https://www.bscsjsn.com/archives/distributed.html(此处用博主自己的链接)，我们对该站点A进行初始配置的时候，抓取间隔设置为1小时抓取一次，但实际抓取过程中，发现该站点内的资讯更新时快时慢，1小时后，这篇资讯还在资讯列表页，甚至再过1小时也还在，那么爬虫每隔1小时都会把这篇资讯抓取进我们的系统中 这个时候，就需要借助redis的Hash类型来帮我们做过滤性去重，假设我们给定站点A一个统一的job_id为108，那么我们在抓取列表页时，需要多加一个步骤； 将字符串job_和站点A任务的真实job_id进行拼接，得到如下字符串job_108； 每次解析到新的详情页链接，需要放到调度队列中重新调度之前，我们先进行判断，判断redis中Hash为job_108的数据中是否已经存在当前链接url，不存在则抓取，并把当前url链接存入到job_108中；如果存在，则说明该url链接已经抓取过了，则丢弃，整个流程就会变成下图： 这样，我们只需要控制好redis中job_108key的失效时间，就能解决上述这种同一数据源重复抓取的问题，大大提升了采集系统的资源利用率 simhash去重 反应比较快的同学其实已经发现了，上述的解决方法有bug存在，如果站点A和站点B分别抓取了站点C的一篇资讯分布式及数据同步，将其url链接变成自己独有的： 站点A-分布式及数据同步-url：https://guaini.blog/archives/distributed.html (举例说明，并不真实存在，域名为博主好友拥有，已得到授权) 站点B-分布式及数据同步-url:https://www.whusan.com/archives/distributed.html(举例说明，并不真实存在，域名为博主好友拥有，已得到授权) 这种情况，其实资讯还是一样的资讯，也还是会被爬虫抓取进我们的系统，这个时候，就需要我们今天的主角-simhash来处理了 simhash介绍 simhash是google用来处理海量文本去重的算法。 google出品，你懂的。 simhash最牛逼的一点就是将一个文档，最后转换成一个64位的字节，暂且称之为特征字，然后判断重复只需要判断他们的特征字的距离是不是<n（根据经验这个n一般取值为3），就可以判断两个文档是否相似 simhash与hash算法的区别 传统Hash算法只负责将原始内容尽量均匀随机地映射为一个签名值，原理上仅相当于伪随机数产生算法。传统hash算法产生的两个签名，如果不相等，除了说明原始内容不相等以外，不再提供任何信息，因为即使原始内容只相差一个字节，所产生的签名也很可能差别很大，所以传统Hash是无法在签名的维度上来衡量原内容的相似度。而SimHash本身属于一种局部敏感哈希算法，它降维生成的hash签名在一定程度上可以表征原内容的相似度。 算法实现过程大致如下： 对文本分词，得到N维特征向量（默认为64维） 为分词设置权重（tf-idf） 为特征向量计算哈希 对所有特征向量加权，累加（目前仅进行非加权累加） 对累加结果，大于零置一，小于零置零 得到文本指纹（fingerprint） 具体的流程实现 simhash的算法具体分为5个步骤：分词、hash、加权、合并、降维，具体过程如下： 分词 给定一段语句或者一段文本，进行分词，得到有效的特征向量，然后为每一个特征向量设置一个5个级别（1—5）权值。例如给定一段语句：“和世界交手这么多年，你是否兴致盎然、风采依旧”，分词后结果为：世界 交手 兴致 盎然 风采 依旧，然后为每个特征向量赋予权值： 世界(5) 交手(4) 兴致(2) 盎然(3) 风采(2) 依旧(1)，其中括号里的数字代表这个单词在整条语句…