Архив за месяц: Март 2016

Поиск ссылок на странице с помощью регулярного выражения

Обычно такие регулярные выражения бывают полезны для написания роботов-пауков. Решил потратить день, но написать одно регулярное выражение чтобы заменить им страницу программного кода, причем весьма запутанного. Но результат превзошел ожидания, программа уменьшилась на 250 строк!

Прелесть этого регулярного выражения в том, что оно не только вычисляет все внешние и внутренние ссылки, включая https и ftp ссылки, так ещё и дробит результат на отдельные элементы. Например можно затем проверять, какой протокол, адрес, имя сервера. Собственно результат предлагаю просмотреть самостоятельно в вашем языке программирования.

(<a)\s+(.*)(href)(\s*)(=)(\s*)([\"']|)(ftp://|https?://|/)([^'\"\s]+)\7(\s*)(.*)>(.*)</a>

В случае PHP нужно комментировать и символ «/», поэтому он будет выглядеть как «\/»
В целом простейший код на PHP для поиска ссылок может выглядеть вот так. Выражение «\7» из него пришлось убрать, так как в PHP-ом интерпретаторе это не работает. В моём учебнике про это предупреждали, что не во всех интерпретаторах эта функция есть. Поэтому выражение стало менее стабильным, может на каких то ссылках и будет глюкаться, но пока что я таковых не обнаружил.



$res=array();
$regEx = "/(<a)\s+(.*)(href)(\s*)(=)(\s*)([\"']|)(ftp:\/\/|https?:\/\/|\/)([^'\"\s]+)(\s*)(.*)>(.*)<\/a>/i";
//Заметьте, что это "жадный" вариант
//Ленивый будет различать ссылки расположенные подряд в одной строчке
//вот его версия, для использования раскомментировать нижнюю строчку:
//regEx="/(<a)\s+?(.*?)(href)(\s*?)(=)(\s*?)([\"']|)(ftp:\/\/|https?:\/\/|\/)([^'\"\s]+?)(\s*?)(.*?)>(.*?)<\/a>/i";
preg_match_all ($regEx,$txt,$res,PREG_SET_ORDER);

            echo '<br>';
                $npp=1;
                foreach ($res as $value) {
                    echo $npp++.". ";
                    for ($index1 = 0; $index1 < count($value); $index1++) {
                        $curvalue=$value[$index1];
                        echo "[ $curvalue ]";
                    }
                    echo "<br>\n";
                }

в переменную $res будет помещен двумерный массив с результатом. Подробнее о функции preg_match_all  можно прочесть здесь: http://phpclub.ru/manrus/f/preg-match-all.html

Это окончательный вариант, резличает ftp://, http://, https:// и относительные адреса. В $8 попадает протокол или «/» если это относительный адрес, а в $9 сам url без протокола, в $12 — текст анкора. URL может быть в одинарных кавычках, двойных кавычках или без кавычек. Исправлен недостаток: если написать такой «неправильный» тег, где адрес взят в кавычки таким образом, что открывается одинарная кавычка, к примеру, а закрывается двойная, этот шаблон воспринимал, как нормальную конструкцию. Теперь это исправлено.

Если нужно сграбить не ссылки, а картинки, тоже с выделением протокола и URL  в отдельные части массива, смотрите здесь http://www.bobpop.ru/?cat=14

Пользуйтесь на здоровье!
Реквизиты для благодярностей внизу страницы.