【问题标题】:Check if Web page was already downloaded检查网页是否已经下载
【发布时间】: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


【解决方案1】:

如果您的问题是检查您的数据库中是否已经存在特定版本的页面以阻止爬虫下载它,那么哈希不是可行的方法,因为无论如何您都必须下载该页面才能生成哈希.

如果您存储了Last-Modified http header 值,您可以在所有后续使用If-Modified-Since http 标头的请求中使用它。 如果你按照这种方式,你将不得不存储

  • 网址
  • 内容
  • 修改日期

存储内容对于进一步处理来说是很好的,但是我建议使用 html 抓取库来为你做这件事。看到这个问题options-for-html-scraping

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

【讨论】:

  • 我已经考虑过使用该标题。但是,当我尝试从响应中检索它时,它不可用(它返回 null),我留下了问题......
  • 您可能找不到能处理大多数情况的单一策略。您可以应用的另一个方法是检查是否有 etag 标头。如果是,则将其存储并在后续请求中使用以执行条件请求。将生成页面的哈希作为最后的手段 - 还要检查是否简单地将内容放入数据库不会比哈希更快。但最重要的是,不要过于频繁地下载页面。 (您可以对 url 应用一些启发式函数 - 即假设其中包含博客的 url 不会比每天更频繁地更改)
猜你喜欢
  • 2010-12-20
  • 1970-01-01
  • 2021-08-08
  • 2021-12-23
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
  • 2020-06-14
  • 2012-05-13
相关资源
最近更新 更多