如何检查网页内容是否已更改?

时间:2015-11-04 07:38:33

标签: python-2.7 hash compare web-crawler

基本上,如果网站上的内容发生变化,我会尝试运行一些代码(Python 2.7),否则请等一下,稍后再检查。

我想要比较哈希,问题是如果页面更改了单个字节或字符,则哈希值会有所不同。因此,例如,如果页面在页面上显示当前日期,则每次散列都不同并告诉我内容已更新。

那么......你会怎么做?你会看一下HTML的 Kb 大小吗?您是否会查看字符串长度并检查长度是否已更改超过 5%,内容已更改"?或者是否存在某种哈希算法,如果只更改了字符串/内容的一小部分,则哈希值保持不变?

关于上次修改 - 遗憾的是并非所有服务器都正确地返回此日期。我认为这不是可靠的解决方案。我认为更好的方法 - 结合散列和内容长度解决方案。检查哈希值,如果更改了 - 检查字符串长度。

6 个答案:

答案 0 :(得分:2)

没有通用的解决方案。

  • 尽可能使用If-modifed-since或HEAD(通常被动态页面忽略)
  • 尽可能使用RSS。
  • 以特定于站点的方式提取最后修改标记(新闻网站有每篇文章的发布日期,可通过XPATH轻松提取)
  • 仅挖掘页面的有趣元素(构建特定于站点的模型),不包括易失性部分
  • 哈希全部内容(对于动态页面无用)

答案 1 :(得分:1)

希望这有帮助。

存储html文件 - 两个版本..

一个是在一小时之前拍摄的html。 - first.html

第二个是现在拍摄的html - second.html

运行命令:

$ diff first.html second.html > diffs.txt

如果差异有一些文字,则文件会被更改。

答案 2 :(得分:1)

最安全的解决方案:

下载内容并使用SHA512内容哈希值创建哈希校验和,将其保存在数据库中并每次比较它。

优点:您不依赖于任何服务器标头,并会检测到任何修改 缺点:带宽使用率过高。您必须每次都下载所有内容。

使用Head

使用HEAD动词请求页面并检查标题标记:

  • Last-Modified:服务器应提供上次生成或修改的页面。
  • ETag:类似校验和的值,由服务器定义,并且应在内容更改后立即更改。

优点:更少的带宽使用和更快的更新 缺点:并非所有服务器都提供并遵守以下准则。如果您发现需要获取数据

,则需要使用GET请求获取真实资源

使用GET

使用GET动词请求页面并使用条件标头标记: * If-Modified-Since:服务器将检查资源是否随着时间的推移而被修改并返回内容或返回304 Not Modified

优点:仍然使用较少的带宽,单程接收数据 缺点:同样不是所有资源都支持此标头。

最后,上述解决方案的混合可能是采取此类行动的最佳方式。

答案 3 :(得分:1)

如果您正在尝试制作可应用于任意网站的工具,那么您仍然可以从使其适用于某些特定网站开始工作 - 重复下载并确定您喜欢的确切差异忽视,试图在不忽视有意义的差异的情况下合理地处理问题。如此快速的动手采样应该会为您提供更多关于您所面临挑战的具体想法。无论您尝试何种解决方案,都可以针对越来越多的网站进行测试,并随时进行调整。

  

你会看看HTML的Kb大小吗?你会看一下字符串长度并检查例如长度是否变化超过5%,内容已被更改"?

那令人难以置信的粗糙,如果可能的话,我会避免这种情况。但是,你需要权衡错误地认为页面不变而错误地认为页面发生变化的成本。

  

或者是否存在某种哈希算法,如果只更改了字符串/内容的一小部分,则哈希值保持不变?

可以制作这样的"哈希"但是很难调整对文档中有意义的更改的敏感度。无论如何,作为一个例子:你可以按照它们在文档中的频率对256个可能的字节值进行排序,并考虑一个2k哈希:你以后可以做一个"差异"在稍后的下载中查看字节值排序的变化程度。 (为了节省内存,您可能只需要执行可打印的ASCII值,甚至可以在标准化大写后使用字母。)

另一种方法是为文档的不同切片生成一组哈希:例如通过标题级别然后段落将其划分为标题与主体,主体,直到您获得至少所需的粒度级别(例如30个切片)。然后你可以说,如果只有2片30片已经改变,你会认为该文件是相同的。

您也可以尝试在散列之前替换某些类型的内容 - 例如使用正则表达式匹配将时间替换为"<time>"

您还可以执行诸如降低容差以更改更多内容,因为您上次处理页面的时间增加,这可能会减少或限制&#34;成本&#34;错误地认为它不变。

答案 4 :(得分:0)

使用git,它具有出色的报告功能,可以处理文件两种状态之间的变化;另外,你不会占用磁盘空间,因为git会为你管理增量。

你甚至可以告诉git忽略“琐碎”的变化,例如添加和删除空白字符以进一步优化搜索。

实际上,这归结为解析git diff -b --numstat HEAD HEAD^的输出;这大致转换为“找到我在所有文件中发生了什么变化,忽略了当前状态和之前状态之间的任何空白变化”;这将产生如下输出:

2       37      en/index.html
进行了2次插入,对en/index.html

进行了37次删除

接下来,您将需要进行一些实验来找到一个“阈值”,您可以在该阈值处考虑更改,以便进一步处理文件;这需要时间,因为你必须训练系统(你也可以自动化这部分,但这是另一个主题)。

除非您有充分的理由这样做 - 请不要将传统的关系数据库用作文件系统。让操作系统处理文件,它非常擅长(关系数据库不是设计用来管理的)。

答案 5 :(得分:0)

您应该执行HTTP HEAD请求(这样就不会下载文件),并查看响应中的“最后修改的”标头。

import requests

response = requests.head(url)
datetime_str = response.headers["last-modified"]

并继续检查该字段是否在while循环中发生变化,并比较日期时间差。

我在Python上做了一个小程序来做到这一点:

https://github.com/javierdechile/check_updates_http