关于采集器采集和重复数据删除的优化

优采云 发布时间: 2020-08-08 15:30

  当我处理漏洞Fuzz采集器时,我曾经从事URL重复数据删除. 当时,我提到了Seay大师的文章以及Internet上的一些零散信息. 我觉得这很简单. 最近遇到了相关的问题,所以我几乎有了重新改进算法的想法.

  首先,对于URL本身的重复数据删除,可以直接处理整个URL. 当提到Internet上的某些文章时,我发现其中大多数使用URL压缩存储. 但是,当数据量很大时,使用这些算法可以大大减少存储空间:

  

  基于磁盘的顺序存储.

  基于哈希算法的存储.

  基于MD5压缩映射的存储.

  基于嵌入式Berkeley DB的存储.

  基于Bloom Filter的存储.

  URL的直接重复数据删除主要涉及存储优化,这不是本文的重点,因此在这里我将不做详细介绍.

  对于URL的逻辑重复数据删除,您需要追求更高的数据可用性,这是进行测试时需要考虑的事情.

  这是seay文章中的相似性重复数据删除算法,大致如下:

  def urlsimilar(url):

hash_size=199999

tmp=urlparse.urlparse(url)

scheme=tmp[0]

netloc=tmp[1]

path=tmp[2][1:]

query=tmp[4]

#First get tail

if len(path.split('/'))>1:

tail=path.split('/')[-1].split('.')[-1]

#print tail

elif len(path.split('/'))==1:

tail=path

else:

tail='1'

#Second get path_length

path_length=len(path.split('/'))-1

#Third get directy list except last

path_list=path.split('/')[:-1]+[tail]

#Fourth hash

path_value=0

for i in range(path_length+1):

if path_length-i==0:

path_value+=hash(path_list[path_length-i])%98765

else:

path_value+=len(path_list[path_length-i])*(10**(i+1))

#get host hash value

netloc_value=hash(hashlib.new("md5",netloc).hexdigest())%hash_size

url_value=hash(hashlib.new("md5",str(path_value+netloc_value)).hexdigest())%hash_size

return url_value

  此函数的一般用途是最终将根据算法返回哈希值,该哈希值也是URL的哈希相似度. 如果两个URL所计算的哈希值最终相等,我们可以判断两个URL具有高度相似性.

  但是应该以seay为例来举例说明此功能(在这里强调,以免被喷洒,稍后我将不对其进行详细说明). 这只是一个简单的演示,无需详细检查. 在粗略的情况下,该算法确实可以消除一些简单的参数重复,但是一旦参数复杂或URL不标准化,对于重复数据删除就不是很好.

  那么在获取URL的过程中,我们还能进行其他哪些小的优化?

  日期和时间命名

  首先,我们可以根据日期进行重复数据删除. 我们知道,在爬网博客和门户之类的某些系统时,经常会遇到以日期命名的目录.

  这些目录可以粗略地概括,并具有类似于以下内容的形式:

  2010-11-11

10-11-11

20101111

  当然,有些文件将以时间+随机值命名,或者它们可能以Unix时间戳命名. 这些可以根据上载和编辑时间来定义.

  作者的建议是使用缓存数据库(例如redis或memcache)直接存储它;或当数据量很大时,请考虑临时存储它,并在需要时进行比较.

  例如,一旦出现以日期和时间命名的目录或静态文件,我们可以考虑以以下格式存储它:

  目录级别

  姓名格式

  URL地址(或压缩的哈希值)

  有人可能会说,在seay提到的情况下,似乎日期的相似性可以解决. 让我们首先看下面的例子. 这里的输出仍然基于上述功能:

  print urlsimilar('http://www.baidu.com/blog/2010-10-11/')

print urlsimilar('http://www.baidu.com/blog/2010-10-13/')

print urlsimilar('http://www.baidu.com/blog/2010-9-13/')

print urlsimilar('http://www.baidu.com/whisper/2010-10-11/')

  输出结果如下:

  110086

110086

37294

4842

  我们可以看到,在正常情况下,确实在同一父目录中,相似性算法可以判断为正确. 但是,一旦日期格式不统一,或者父目录中存在某些差异,就不是一个很好的判断.

  当然,我们还可以使用机器学习来完成重复数据删除的工作. 但是在简化工作方面,您仍然可以根据规则匹配使用一些小技巧来完成它.

  删除静态文件

  我们知道,在爬网URL的过程中,我们还会遇到许多静态文件,例如shtml,html,css等. 在大多数情况下,这些文件是没有意义的. 除非测试人员倾向于使用完整的采集方法,否则“我宁愿错误地杀死一百个人,也不会错过任何一个. ”

  这时,我们可以配置黑名单并创建文件后缀规则库进行过滤.

  当然,带有静态后缀的URL链接也可能与参数混淆. 个人建议是,用于回调的json和xml之类的URL可能会存储敏感内容,并尽量不要移动它们. 对于其他类型的静态文件,仍然采用分离参数的方法,最后对URL进行重复数据删除和存储.

  针对特定情况进行过滤

  在抓取特定网站时,我们可以对其进行预配置并指定过滤某些目录和页面以节省大量时间和资源.

  相反,我们还可以指定仅爬网指定目录中的页面,并定位所需的内容.

  感知敏感页面

  

  在seay提出的演示算法中,在这种情况下存在某些限制. 例如,我们需要在敏感目录中获取尽可能多的文件信息. 例如,如果我们爬到后台管理目录,则可能会遇到以下情况:

  print urlsimilar('http://www.baidu.com/blog/admin/login.php')

print urlsimilar('http://www.baidu.com/blog/admin/manage_index.php')

print urlsimilar('http://www.baidu.com/blog/admin/test.css')

  输出结果如下:

  40768

40768

40768

  显然有问题,不是吗?

  我们当然可以监视敏感的页面关键字;或者我们可以指定一个后缀文件来执行白名单监控.

  但是一旦您执行了此操作,并且想要使用以前的哈希算法,则您自己定义的过滤器函数的优先级必须大于该算法. 另外,在这样做的过程中,还应考虑过滤成本问题,建议采用选择性激活.

  对高频敏感目录的优惠待遇

  也许在爬网过程中,某些爬网程序还使用目录爆炸的方法. 如果采用此方法并且匹配成功,则可以对目录中的内容使用单独的过滤规则,以避免误判重复数据删除算法.

  过滤响应页面

  

  对于某些网站,由于链接无效,许多页面可能被标记为404页和50x错误. 另外,当您无权访问时,网站可能会进行30倍重定向和403目录限制.

  这些页面没有实质性内容,并且在大多数情况下是没有意义的. 我们可以在配置文件中将需要爬网的页面类型列入白名单,例如保留403个页面,或在跳转(之后)页面之前访问30倍.

  WAF(警告)页面过滤

  

  某些网站可能已安装WAF. 如果访问频率太快,可能会出现WAF警告页面. 在CMS自身施加限制的情况下,某些不存在的页面将以20x的响应代码显示.

  当然,我们可以通过代理的分布式交换来解决其中的一些问题,因此在此不再赘述.

  这时,我们可以配置相应的次数阈值. 如果某些页面出现过多次,则可以将它们标记为警告(WAF)页面,然后进行过滤. 在此处可以识别页面,您可以使用黑名单关键字对其进行标记;或尝试计算页面哈希值,例如:

  content = urllib2.urlopen('http://www.test.com/').read()

md5_sum = hashlib.md5()

md5_sum.update(content)

print md5_sum.hexdigest()

  当然,当我们实际计算页面哈希值并进行关键字监控时,由于存在反爬虫机制(例如,添加随机值). 当然,这也会消耗更多的时间和机器资源. 但是在某些特定情况下,它也可能带来意想不到的收益.

  删除无意义的参数页面

  在采集页面的过程中,我们可能还会遇到一些无意义的,经常出现的多参数页面. 这样的页面可以是回调页面,也可以是临时呈现的随机页面.

  在这里,您可以通过以前的WAF(警告)方法进行过滤. 当然,使用以前的哈希算法也可以应付大多数情况. 毕竟,这种网站的URL是受限制的,并且不需要为多个功能消耗更多的资源,因此收益大于损失.

  JS代码中的URL

  当我们提取js代码时,也就是说,当我们遇到诸如ajax之类的交互时,我们可能会遇到需要拼接的GET请求或可以直接访问的POST请求.

  这种URL地址最好与phantomjs之类的webkit结合使用,以更方便地进行动态拼接.

  它们看起来很特殊,可能仅返回状态代码,或者可能返回实质上敏感的内容. 在这种情况下,有必要根据采集器的要求调整搜寻过滤规则.

  摘要

  此处的作者旨在针对类似URL的重复数据删除提出一些小的优化措施,这些效果可能有限,或者可能不令人满意.

  欢迎提出建议. 我希望减少喜欢喷涂的童鞋,并增加讨论和鼓励.

  参考文章

  如何避免重复抓取同一网页

  谈论动态采集器和重复数据删除

  Web采集器: 使用BloomFilter进行URL重复数据删除策略

  实用科普: 履带技术分析. 编写采集器时的注意事项

  Web爬网程序(蜘蛛)URL重复数据删除设计URL重复数据删除设计

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线