【问题标题】:C# What is the best way to compute a hash of an xml feedC#计算xml提要哈希的最佳方法是什么
【发布时间】:2011-10-24 18:37:43
【问题描述】:

我想检测提要是否已更改,我能想到的唯一方法是对 xml 文档的内容进行哈希处理,并将其与提要的最后一个哈希值进行比较。

我使用 XmlReader 是因为 SyndicationFeed 使用它,所以理想情况下我不想加载联合提要,除非提要已更新。

XmlReader reader = XmlReader.Create("http://www.extremetech.com/feed");
SyndicationFeed feed = SyndicationFeed.Load(reader);

【问题讨论】:

  • 哈希冲突的后果是什么?也就是说,假设两个文档具有相同的哈希值。可能发生的最糟糕的事情是什么?
  • 我做了更多测试,如果这是您的确切提要,则此提要中的一些 cmets 会定期更改,即使非注释 xml 标签从未更改,所以我不认为哈希方法将完全奏效
  • @MerickOWA 我想我会使用 SyndicationItem 中的 ID .. 可能会更容易:) 这样,如果编辑提要标题或文章就不会成为问题!
  • @superlogical 我添加了另一种不依赖散列的可能性,它可能通常可以工作,但它依赖于服务器。

标签: c# xmlreader


【解决方案1】:

为什么不只检查提要的LastUpdatedTime?这是一种告诉您某些东西是否新的内置方式。您只需跟踪 LastUpdatedTime 并定期将其与最新的 LastUpdatedTime 进行比较,而不是散列和​​存储散列:

using System;
using System.ServiceModel.Syndication;
using System.Xml;

public class MyClass
{
    private static DateTime _lastFeedTime = new DateTime(2011, 10, 10);

    public static void Main()
    {
        XmlReader reader = XmlReader.Create("http://www.extremetech.com/feed");
        SyndicationFeed feed = SyndicationFeed.Load(reader);

        if (feed.LastUpdatedTime.LocalDateTime > _lastFeedTime)
        {
            _lastFeedTime = feed.LastUpdatedTime.LocalDateTime;

            // load feed...
        }
    }
}

【讨论】:

  • 是的,我考虑过这一点,但我只是不知道考虑到某些提要可能不会更新该值,这有多可靠。但话又说回来,我可能完全错了 :) Wordpress 总是很好用吗?我要索引的大部分提要都是基于 Wordpress 的
  • LastUpdatedTime 是完全不可靠的,因为它依赖于服务器的配合。
  • 先尝试一下 DateTime。除非必须,否则不要假设和解决问题。是的,您依赖于符合标准的第 3 方,但这种情况一直都在发生。而且我想不出比 LastUpdatedTime 更有用的元数据来遵守。不遵守规定应受到体罚。 ;-)
  • @PaulSasik 我想我会使用 SyndicationItem 中的 ID
【解决方案2】:

如果你真的想走散列方式,你可以这样做:

var client = new WebClient();

var content = client.DownloadData("http://www.extremetech.com/feed");

var hash = MD5.Create().ComputeHash(content);
var hashString = Convert.ToBase64String(hash);

// you can then compare hashes and if changed load it this way
XmlReader reader = XmlReader.Create(new MemoryStream(content));

当然,这样你会发现内容的任何变化,即使是最轻微的变化。

恕我直言,最好的方法是加载提要并仅对文章的内容进行哈希处理,您可以像这样对任何字符串进行哈希处理:

var toHash = "string to hash";

var hash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(toHash);
var hashString = Convert.ToBase64String(hash);

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    哈希方法在这种情况下不起作用,因为某些服务器端缓存添加了 XML 注释,即使实际提要从未更改,也会经常频繁地添加。

    您可以对这个提要做的一件事是使用 HTTP 条件请求来要求服务器仅在数据自您上次请求后实际被修改时才向您提供数据。

    例如:

    您将有一个全局/成员变量来保存您的提要中最后修改的日期时间

        var lastModified = DateTime.MinValue;
    

    那么每次你都会发出如下请求

        var request = (HttpWebRequest)WebRequest.Create( "http://www.extremetech.com/feed" );
        request.IfModifiedSince = lastModified; 
        try {
    
          using ( var response = (HttpWebResponse)request.GetResponse() ) {
    
            lastModified  = response.LastModified;
    
            using ( var stream = response.GetResponseStream() ) {
    
              //*** parsing the stream
              var reader = XmlReader.Create( stream );
              SyndicationFeed feed = SyndicationFeed.Load( reader );
              }
            }
          }
        catch ( WebException e ) {
          var response = (HttpWebResponse)e.Response;
          if ( response.StatusCode != HttpStatusCode.NotModified )
            throw; // rethrow an unexpected web exception
          }
    

    【讨论】:

    • +1 用于正确使用 HTTP。您还可以使用响应中的 EXPIRES 标头(如果存在)和提要中的元数据(最后更新日期、更新周期和更新频率)来指导您下次检查更新的时间/频率。
    猜你喜欢
    • 2010-10-11
    • 1970-01-01
    • 2021-09-02
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 2012-06-23
    • 2016-09-25
    相关资源
    最近更新 更多