Найти все внешние ссылки с помощью Simple HTML Dom Parser и регулярных выражений?

Как найти все внешние ссылки на странице с помощью регулярных выражений и простого парсера HTML DOM? У меня есть следующий код, чтобы найти все ссылки.

<?php
    include_once('simple_html_dom.php');
    $url = "http://www.tokyobit.com";
    $html = new simple_html_dom();
    $html->load_file($url);
    foreach($html->find('a') as $a){
        echo $a;
    }
?>

Как добавить регулярное выражение для поиска всех ссылок, начинающихся с http://, https:// или ftp://?

foreach($html->find('a') as $a){
    $regex = ; //regex here
    if(preg_match_all($regex, $a, $matches)){
        foreach($matches as $match){
            echo $match . '<br />';
        }
    }
}

person LightningBoltϟ    schedule 05.12.2013    source источник
comment
Лично я думаю, что попытка парсить HTML с помощью php ставит вас на полпути к написанию синтаксического анализатора HTML. У вас есть доступ к DOM на Js? Было бы намного проще просто написать несколько обратных вызовов ajax...   -  person The Marlboro Man    schedule 05.12.2013


Ответы (4)


Вы можете использовать пользовательский strpos для использования массива в качестве иглы.

Сначала вам понадобится эта функция

function strposa($haystack, $needle, $offset=0) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $query) {
        if(strpos($haystack, $query, $offset) !== false) return true; // stop on first    true result
    }
    return false;
}

Затем в вашем коде

$needle = array("ftp://","http://","https://");
foreach($html->find('a') as $a){
    if(strposa($a, $needle){
        echo $matches;
    }
}
person Ali    schedule 05.12.2013

Попробуй это:

foreach($html->find('a') as $a){
    if(preg_match('#^(?:https?|ftp)://.+$#', $a->href)){
        echo $matches;
    }
}
person Stephan    schedule 05.12.2013

Вы можете сделать это следующим образом:

include_once('simple_html_dom.php');
$url = "http://www.tokyobit.com";
$html = new simple_html_dom();
$html->load_file($url);
$result = array();

foreach($html->find('a') as $a){
    $href = $a->href;
    if (strpos($href, '://', 3)!==false) $result[] = $href;
}

print_r($result);
person Casimir et Hippolyte    schedule 05.12.2013
comment
@pguardiario: 3 является третьим параметром и указывает индекс, с которого вы начинаете поиск в строке. Поскольку наименьшее возможное начало строки — ftp (индекс от 0 до 2), первая позиция, где вы можете найти ://, — это 3 (не нужно сначала проверять 3). - person Casimir et Hippolyte; 06.12.2013
comment
Однако, если подумать, везде, где появляется ://, достаточно для совпадения. - person pguardiario; 06.12.2013
comment
@pguardiario: действительно, но не забывайте, что вы ищете URL-адрес внутри атрибута href, это не случайная строка. - person Casimir et Hippolyte; 06.12.2013
comment
Я знаю это. Я говорю, что, например, «://foo.com» — это гиперссылка, и она тоже должна совпадать. - person pguardiario; 07.12.2013

Измените переменную $regex на:

$regex = "#(https?|ftp)://.#";
person LightningBoltϟ    schedule 05.12.2013
comment
Вы можете упростить регулярное выражение, используя, например, другой закрывающий символ ~ или #. Это позволит избежать экранирования /. - person Stephan; 05.12.2013