如何加快检查HTML链接的类?

时间:2011-07-05 20:05:58

标签: php html http

我拼凑了一个检查链接的课程。它有效,但速度很慢:

该类基本上解析HTML字符串并返回href和src属性的所有无效链接。以下是我如何使用它:

$class = new Validurl(array('html' => file_get_contents('http://google.com')));

$invalid_links = $class->check_links();

print_r($invalid_links);

HTML有很多链接,它变得非常慢,我知道它必须通过每个链接并遵循它,但也许有经验的人可以给我一些关于如何加快它的指示。

以下是代码:

class Validurl{

    private $html = '';

    public function __construct($params){ 

        $this->html = $params['html'];

    } 

    public function check_links(){

        $invalid_links = array();    

        $all_links = $this->get_links();

        foreach($all_links as $link){

            if(!$this->is_valid_url($link['url'])){

                array_push($invalid_links, $link);

            }

        }

        return  $invalid_links;

    }

    private function get_links() {

        $xml = new DOMDocument();

        @$xml->loadHTML($this->html);

        $links = array();

        foreach($xml->getElementsByTagName('a') as $link) {
            $links[] = array('type' => 'url', 'url' => $link->getAttribute('href'), 'text' => $link->nodeValue);
        }

        foreach($xml->getElementsByTagName('img') as $link) {
            $links[] = array('type' => 'img', 'url' => $link->getAttribute('src'));
        }        

        return $links;
    }

    private function is_valid_url($url){

         if ((strpos($url, "http")) === false) $url = "http://" . $url;

         if (is_array(@get_headers($url))){

              return true;

         }else{

             return false;

         }
    }

}

2 个答案:

答案 0 :(得分:2)

首先,当你可以直接迭代getElementsByTagName()的结果时,我不会将链接和图像推送到数组中,然后遍历数组。你必须为< a>做两次。和< img>标签,但是如果你将检查逻辑分成一个函数,你只需要为每一轮调用它。

其次,get_headers()很慢,基于PHP manual page的评论。您应该以某种方式使用cUrl(在comment on the same page中找到):

function get_headers_curl($url) 
{ 
    $ch = curl_init(); 

    curl_setopt($ch, CURLOPT_URL,            $url); 
    curl_setopt($ch, CURLOPT_HEADER,         true); 
    curl_setopt($ch, CURLOPT_NOBODY,         true); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($ch, CURLOPT_TIMEOUT,        15); 

    $r = curl_exec($ch); 
    $r = split("\n", $r); 
    return $r; 
}

更新:,是的,某种缓存也可以提供帮助,例如:一个SQLITE数据库,其中包含一个用于链接和结果的表,您可以像每天一样清除该数据库。

答案 1 :(得分:0)

您可以缓存结果(在DB中,例如:键值存储),以便您的验证器假定如果链接有效,它将在24小时或一周或类似的情况下有效。