【发布时间】:2021-02-04 08:18:58
【问题描述】:
上下文
我编写了一个 Java 爬虫,它会定期下载 Google 上列出的包含一组关键字的页面。这些页面要么是静态的(即其内容不会改变)要么是动态的(即其内容会发生变化,因为它是用户生成的或意味着每天更新/ecc ...)。爬虫将每个页面存储在 MongoDB 数据库中,保存:
- 标题
- 网址
- 内容(即整个页面的 HTML 内容)
问题
但是,页面可能会被多次下载,我的目标是了解某个页面是否已经存在于我的数据库中并防止爬虫再次下载它。
我的解决方案
因此,我使用以下哈希函数对页面内容进行哈希处理:
private long hashFunction(String text) {
long h = 1125899906842597L;
int len = text.length();
for (int i = 0; i < len; i++)
h = 31*h + text.charAt(i);
return h;
}
并将哈希值与之前列出的字段一起存储在数据库中。因此,每次下载页面时,我都会对其内容进行哈希处理,如果哈希值已包含在数据库中,则丢弃该页面。
为什么我的解决方案不起作用
不幸的是,页面可能会发生一些变化,但总体上仍然提出相同的内容。举个例子:
- 从 Twitter 下载的页面在每次请求时都会更改一个“身份验证令牌”
因此,我的数据库中有很多重复项,它们报告的内容相同,只是在某些字符上有所不同。
问题
是否有任何更智能的方法来跟踪页面之间的差异,以便在更改很小的情况下,我可以识别出该页面已经在数据库中?显然,该解决方案应该具有高性能,因为数据库可能会变得非常大,并且与大型文档执行精确匹配可能会很昂贵。
[EDIT] 一个暂定的解决方案(可能有意义...)
我想过:
- 仅从页面中提取正文
- 删除标签(即,<...> 形式的所有内容)
- 计算在此操作中幸存的文本部分的哈希
有道理吗?
【问题讨论】:
-
可能不是一个绝妙的解决方案,但是如果您只从 HTML 文件的 BODY 部分生成散列呢?
-
我已经考虑过了,但是它经常在小部分发生变化(例如,重定向链接,身份验证......),所以这并不能解决问题,很遗憾。
标签: java html performance mongodb hash