【问题标题】:Read only when the XML data is updated更新 XML 数据时只读
【发布时间】:2010-11-20 07:51:06
【问题描述】:

我可以用 PHP 解析 RSS - 我正在寻找的是能够只获取更新的内容,如果 RSS 没有新的更新,则什么也不做。

例如,我有这个RSS File,如果没有新内容,什么都不会发生,但如果有新内容,我想向我的用户发送最新的 RSS 更新,而不是重新发送他们已有的内容。我只解析和发送标题和链接。

我使用 cronjob 每小时检查一次更新。我的问题是我怎么知道提要现在已经更新,而不是与上一个相同?这是我用来阅读 RSS 的PHP file。我是将最后的内容写入文件并进行比较,还是有任何其他方法可以确定内容现在与上一个不同?

更新:我不得不重新发布这篇文章,因为我仍在努力让它发挥作用。虽然我接受了一些答案,但它们很难实现,例如散列选项最初看起来是个好主意,但由于要检查数千个 RSS,几乎不可能将它们全部散列。

再次,有人建议使用 HTTP 缓存 - 我找不到简单的演示,所以我几乎被卡住了。

任何进一步的建议将不胜感激。

【问题讨论】:

  • 您是从提要中获取信息并将其发送给用户还是仅转发提要本身?如果是后者,让用户决定何时重新阅读提要。否则就没有意义了。
  • 我只获取标题和链接并将它们发送给用户。所以,我不想再次发送相同的标题。我想要的是如果没有新内容,什么都不做,但是如果有新的更新,解析它并发送更新。

标签: php xml rss


【解决方案1】:

您的客户总是会询问您的 Feed 数据,因此您无法控制他们何时询问他们。我认为大多数提要阅读器不遵守 HTTP Cache Control / Expires 标头,因此您不能依赖使用 HTTP 规范并利用 HTTP 缓存。

我认为您最好的选择是仅缓存您的最后一个响应并从缓存中发送所有后续请求 - 在进行更改时适当地更新缓存。实际上,这意味着您响应每个客户端及其陈旧数据的成本几乎接近于 0,如果您只是从内存缓存或文件系统中提取数据。

【讨论】:

  • 感谢 Cody 的评论 - 但我们的系统旨在在有更新时向客户发送信息。事实上,它是一个短信系统,应该只发送最新信息,而不是重复上一条信息
  • @Cody 支持 HTTP 条件 GET 总是一个好主意。您是否有任何参考资料来支持您声称它不受客户尊重的说法?
【解决方案2】:

由于 RSS 的多样性,您提出的问题没有简单的解决方案。 主要问题是如何确定 rss 项的唯一性。它可以是引导、发布时间或内容本身,但自动检测可能很棘手。

一旦您知道唯一性标准,您就可以保留所有“旧”项目并将它们与您收到的最新项目进行比较。

HTTP Cache Control 和 Expires 标头可用作支持该功能的站点的优化,但不幸的是有些不支持。

【讨论】:

  • 感谢 Genndy,您的回复给了我一个想法。我现在将标题写入一个文件,并在 cronjob 运行时将它们与新内容进行比较。如果他们新的没有出现在旧列表中,我将把它发送出去。这意味着我必须每周清除整个列表,以防止它在服务器上失控。至少,这是我现在唯一的选择。
  • 这只有在您确定项目标题是唯一的情况下才有效。一般来说,您可以轻松找到并非如此的提要。
  • GUID/UUID 将是一个更好的比较候选者,它意味着全局(概率上)是唯一的。
【解决方案3】:

HTTP Conditional GET 可能与您想要的一样接近。

【讨论】:

    【解决方案4】:

    您可以通过两种方式为此使用哈希:

    1. 为简化更新 - 请求更新时,您对整个提要进行哈希处理,并将结果与​​上次的哈希值进行比较 - 如果它们相同,您就知道提要没有更改,甚至可以在解析它之前停止。
    2. 识别更改 - 在解析时,您对每个项目进行哈希处理,并将其与之前运行存储的哈希值进行比较。如果它匹配一个,你就知道你以前见过它。

    如果有问题的提要为其项目提供 guid,您可以通过存储 guid哈希对来优化此过程。这将使比较更快,因为您只会将项目与已知的先前版本进行比较,而不是与所有先前的项目进行比较。

    您仍然需要一些过期/清除机制来将存储的哈希数量保持在范围内,但鉴于您只存储相对较短的字符串(取决于所选的哈希算法),您应该能够保留相当多的积压在遇到性能问题之前。

    【讨论】:

    • 不使用哈希实际上更快,而是比较字节包....(对于哈希,您正在读取整个两个文件,无论如何,并激活哈希算法 - 读取整个文件肯定比读取所需的更多,has 算法肯定不仅仅是比较字节)。
    • @Itay:当然,散列会对生成产生影响,但这里的重点是存储以前的条目并与这些条目进行比较。要进行字节比较,您必须将整个提要和整个提要项目存储在数据库中,根据提要,这可能是相当大量的数据。写和读这些也需要时间,但尤其是减少了在给定存储空间下可以保留的过去条目的数量。
    • @Itay - 您可以对旧内容进行一次哈希处理,因此您只需对新内容进行哈希处理。如果内容很多,你省去重​​读旧内容,你只读旧哈希。
    【解决方案5】:

    @Henrik 的解决方案是正确的,但是向您提供哈希数据的示例可能是最简单的:

    // hash the three channel variables
    $hash = sha1($channel_title . $channel_link . $channel_desc);
    
    // here you should check the currently stored database hashed 
    // value against current hash value to see if any channel variables
    // have recently changed
    if ($database_hash != $hash) {
        // you need to update the channel data in your database
        // including the new hash value
    }
    
    for ($i = 0; $i < 3; $i++) {
    
        // hash the item values
        $hash = $item_title . $item_link . $item_description
    
        // here you should check the currently stored database hashed 
        // value against all item hash values to see if any item variables
        // have recently changed
        if ($database_hash != $hash) {
            // you need to update the item data in your database
            // including the new hash value
        }
    
    }
    

    另外,如果您想快速检查以确定 XML 文件中的任何数据是否发生了任何变化,您可以将 XML 散列为字符串。您应该存储此值并在每次运行 cronjob 时检查该值是否已更改(表明 XML 文件中的某些数据已更改)。

    $overall_hash = sha1($xmlDoc->saveXML());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多