Java 检查网页是否已下载

Java 检查网页是否已下载,java,html,performance,mongodb,hash,Java,Html,Performance,Mongodb,Hash,上下文 我编写了一个Java爬虫,它定期下载Google上列出的包含一组关键字的页面。这些页面既可以是静态的(即,其内容不改变),也可以是动态的(即,其内容因用户生成或打算每天更新/ecc…)而改变。爬虫程序将每个页面存储在MongoDB数据库中,保存: 头衔 网址 内容(即整个页面的HTML内容) 问题 但是,页面可能会被下载多次,我的目标是了解某个页面是否已经存在于我的数据库中,并防止爬虫再次下载它 我的解决方案 因此,我使用以下散列函数对页面内容进行散列: private long h

上下文

我编写了一个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;
}
专用长哈希函数(字符串文本){
长h=1125899906842597L;
int len=text.length();
对于(int i=0;i
以及将散列值与先前列出的字段一起存储在数据库中。因此,每次下载页面时,我都会对其内容进行散列,如果散列值已包含在数据库中,则丢弃该页面

为什么我的解决方案不起作用

不幸的是,页面可能会有一点变化,仍然建议在所有相同的内容。例如:

  • 从Twitter下载的页面在每次请求时都会更改“身份验证令牌”
因此,我的数据库中有很多副本,它们报告相同的内容,只是在某些字符上有所不同

问题

有没有更智能的方法来跟踪页面之间的差异,以便在更改最小的情况下,我可以识别出该页面已经在数据库中?显然,解决方案应该具有高性能,因为数据库可能会变得非常大,并且与大型文档进行精确匹配可能会非常昂贵

[编辑]暂定解决方案(可能有意义…

我想:

  • 仅从页面中提取正文
  • 删除标签(即表单中的所有内容)
  • 计算此操作中幸存的文本部分的哈希值

它是否有意义?

如果您的问题是检查数据库中是否已经存在某个页面的特定版本,以阻止爬虫下载该页面,则哈希不是解决方法,因为您必须下载该页面才能生成哈希

如果存储该值,则可以在使用http头的所有后续请求中使用它。 如果你这样做,你将不得不存储

  • 网址
  • 内容
  • 修改日期
存储内容对于进一步的处理是很好的,但我建议您使用html刮取库来完成这项工作。看到这个问题了吗


此外,我认为最好不要经常下载数据(可能这取决于你的问题领域),但你可以简单地假设这个页面在过去20分钟左右没有变化。如果页面经常更改,您将落后于最新版本。

可能不是一个很好的解决方案,但如果您仅从HTML文件的正文部分生成哈希,会怎么样?我已经考虑过了,但它通常会在小部分更改(例如重定向链接、身份验证…),因此这并不能解决问题,不幸的是,我已经考虑过使用这个标题了。但是,当我试图从响应中检索它时,它不可用(它返回null),我就有问题了……您可能找不到一种策略可以处理大多数情况。您可以应用的另一个方法是检查是否存在etag头。如果是,则存储它并在后续请求中使用它来执行条件请求。将生成页面散列作为最后手段——还要检查是否简单地将内容放入数据库不会比散列更快。但最重要的是,不要经常下载网页。(您可以对url应用一些启发式函数-即,假设包含博客的url不会比每天更频繁地更改)