【问题标题】:How do I check for valid (not dead) links programmatically using PHP?如何使用 PHP 以编程方式检查有效(非死)链接?
【发布时间】:2010-09-19 15:49:48
【问题描述】:

给定一个 url 列表,我想检查每个 url:

  • 返回 200 OK 状态码
  • 在 X 时间内返回响应

最终目标是一个能够将网址标记为可能已损坏的系统,以便管理员可以查看它们。

脚本将用 PHP 编写,并且很可能每天通过 cron 运行。

该脚本一次将处理大约 1000 个网址。

问题分为两部分:

  • 这样的操作有什么大问题吗?您遇到了什么问题?
  • 考虑到准确性和性能,在 PHP 中检查 url 状态的最佳方法是什么?

【问题讨论】:

  • 200 并不是唯一好的代码。 3xx 代码意味着重定向,在许多情况下,您想要的页面就是您被带到的地方(但不能保证)。 401 也不一定是“坏”,但它不是 200。
  • 您应该注意不要连续锤击同一个网站或the owner might get upset。也许对列表进行排序,对于来自同一站点的多个 URL,在下一个请求之前会产生某种类型的延迟(或者转到另一个站点,稍后再返回该站点)。

标签: php url cron


【解决方案1】:
  1. fopen() 支持 http URI。
  2. 如果您需要更大的灵活性(例如超时),请查看 cURL 扩展。

【讨论】:

  • 不要使用 fopen() - 它不支持重定向等。
【解决方案2】:

查看 cURL。有一个 PHP 库。

还有一个 cURL 的可执行版本,因此您甚至可以用 bash 编写脚本。

【讨论】:

    【解决方案3】:

    您无疑会遇到的一个潜在问题是,当运行此脚本的机器失去对 Internet 的访问权限时...您将得到 1000 个误报。

    您的脚本最好保留某种类型的历史记录并仅在失败 5 天后报告失败。

    此外,在继续进行标准检查之前,脚本应该以某种方式进行自我检查(例如检查已知良好的网站 [google?])。

    【讨论】:

    • 是的,最终应用程序有一个主要的历史组件。为了简单起见,我把它排除在外。此外,检查一些知道好的 url 是一个好主意。谢谢。 :)
    【解决方案4】:

    我实际上用 PHP 编写了一些东西,它通过 5k+ URL 的数据库执行此操作。我使用了 PEAR 类HTTP_Request,它有一个名为getResponseCode() 的方法。我只是遍历 URL,将它们传递给 getResponseCode 并评估响应。

    但是,它不适用于 FTP 地址、不以 http 或 https 开头的 URL(未经证实,但我相信是这种情况)以及安全证书无效的站点(未找到 0)。此外,服务器未找到返回 0(没有状态码)。

    而且它可能比 cURL 更容易,因为您包含一些文件并使用单个函数来获取整数代码。

    【讨论】:

      【解决方案5】:

      看来这可能是curl 的工作。

      如果你没有被 PHP 困住,Perl 的 LWP 也可能是一个答案。

      【讨论】:

      • 阿门 LWP。 Perl 更适合,因为也不涉及超时。更不用说,它摇摆不定。 :)
      【解决方案6】:

      您还应该注意返回 301 或 302 HTTP 响应的 URL,这些响应重定向到另一个页面。通常这并不意味着链接无效。例如,http://amazon.com 返回 301 并重定向到 http://www.amazon.com/

      【讨论】:

        【解决方案7】:

        使用 PHP cURL 扩展。与 fopen() 不同,它还可以发出足以检查 URL 可用性并为您节省大量带宽的 HTTP HEAD 请求,因为您不必下载整个页面的正文进行检查。

        作为起点,您可以使用如下函数:

        function is_available($url, $timeout = 30) {
            $ch = curl_init(); // get cURL handle
        
            // set cURL options
            $opts = array(CURLOPT_RETURNTRANSFER => true, // do not output to browser
                          CURLOPT_URL => $url,            // set URL
                          CURLOPT_NOBODY => true,         // do a HEAD request only
                          CURLOPT_TIMEOUT => $timeout);   // set timeout
            curl_setopt_array($ch, $opts); 
        
            curl_exec($ch); // do it!
        
            $retval = curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200; // check if HTTP OK
        
            curl_close($ch); // close handle
        
            return $retval;
        }
        

        但是,有很多可能的优化:您可能希望重复使用 cURL 实例,如果每个主机检查多个 URL,甚至可以重复使用连接。

        哦,这段代码确实严格检查 HTTP 响应代码 200。它不遵循重定向 (302)——但也有一个 cURL 选项。

        【讨论】:

          【解决方案8】:

          仅返回 200 响应是不够的;很多有效链接在原所有者未能续订的情况下,变成色情/赌博门户后,还会继续返回“200”。

          域名抢注者通常会确保其域中的每个 URL 返回 200。

          【讨论】:

          • 这也是一个真正的问题。检查好(或坏)的 URL 不是一个小问题。
          【解决方案9】:

          您只需要一个 bash 脚本来执行此操作。请在类似的帖子here 上查看我的答案。它是一种单线器,可重用 HTTP 连接以显着提高速度,针对临时错误重试 n 次并遵循重定向。

          【讨论】:

            猜你喜欢
            • 2012-02-29
            • 2012-06-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-05-10
            • 2011-12-06
            相关资源
            最近更新 更多