|
|
|
| Здравствуйте.
В поиске очень много топиков на эту тему, но нужного ответа не нашел. Сам уже третий час бъюсь, не получается за один проход. Задача у меня: вынуть относительные пути из ссылок.
Ссылки могут быть вида:
<a href="http:lalala.html">
<a href='http:lalala.html'>
<a href="http:lalala.lalala.ru">
<a href='http:lalala.lalala.ru'>
<a href='http:lalala.lalala.ru/lalala.html'>
<a href="lalala/lalala">
<a href='lalala.html?la=lalala'>
<a href='lalala.html?la=lalala' onclick='Pshel()>
.....
| в общем все возможные варианты.
Нужно вытащить только относительные пути. Ну можно с хвостом: lalala.html?la=lalala.
Причем проигнорировать абсолютные.
Поможите, люди добрые!
Как вынуть, я знаю, а вот паттерн...
Спасибо. | |
|
|
|
|
|
|
|
для: Николай2357
(06.08.2008 в 14:25)
| | если даже предположить что в ссылках после http: нет слэшей потомучто они там как-бы должны быть,
всёравно непонятно вытащить ссылки имелось ввиду вытащить адреса на ходящиеся в атрибуте href или все теги <a>,
и почему нет закрывающих тегов </a>
наверное поможет применение отрицающей подмаски (?! .... )
например вот такой не самый быстрый и не самый точный шаблон
<pre><?
$txt = '<a href="http:lalala.html">
<a href=\'http://lalala.html\'>
<a href="ftp://lala.lalala.ru">
<a href=\'udp://lala.lalala.ru\'>
<a href=\'http://lalala.lalala.ru/lalala.html\'>
<a onclick=\'\' href="../../lalala/lalala">
<a href=lalala.html?la=lala color=red>
<a href=\'lalala.html?la=lalala\' onclick=\'\'>';
preg_match_all('#<a[^>]+?href=[\'"]?((?!(?:htt|ud|ft)p://)[^\'" >]+)#si', $txt, $txt);
print_r($txt[1]);
?></pre>
|
здесь после совпадения <a[^>]+?href=[\'"]?,
"[^>]+?" вместо ".+?" для более точного поиска , т.к. может попасться ссылка без href, например <a name=test></a> и href , будет искаться за пределами ссылки.
после нажождения href= и кавычки ,если есть,
открывается захватывающая подмаска ( ... )
в которую предполагается захватить строку адреса
, и тут идёт проверка на совпадение с "(?:htt|ud|ft)p://"
, (?: .... ) - незахватывающая подмаска . Здесь нужна для группировки
альтернатив htt|ud|ft (например такие альтернативы работают медленнее чем классы символов , типа [htudf]{2,3}
, но выбирать часто не приходится )
тк вот , допустим совпавшее "(?:htt|ud|ft)p://" , находится внутри
подмаски (?! .... ) , и поиск получает несовпадение с шаблоном и начинает искать всё с начала, возвращаясь на +1 байт от байта предидущего начала
если-же не находится то что в (?! .... )
, дальше уже выбирается текст совпадающий с классом символов [^\'" >]+, что в большинстве случаев совпадает с содержимым атрибута href
, но бывают даже ссылки типа <a href=""></a>, и они работают ,
или <a href="javascript:....."></a>, и это не адреса.
более точные шаблоны будут более медленными и сложными,
так-что смело можно пробовать использовать шаблон типа
'#<a[^>]+?href=[\'"]?((?!http://)[^\'" >]+)#si
если я правильно понял что нужно искать | |
|
|
|
|
|
|
|
для: xx77
(06.08.2008 в 23:40)
| | Огромное спасибо за такой подробный комментарий, теперь я точно разберусь!
Там есть мелкие ньансы типа href='#', но это мелочи, главное, что теперь есть граматная основа. Всего конечно не предусмотришь, да и не надо. Есть другие способы с ними бороться.
Еще раз спасибо, впечатляет. | |
|
|
|
|
|
|
|
для: Николай2357
(07.08.2008 в 10:31)
| | с ссылками на якоря в адресе попроще .
текст после # бывает нужен практически только браузерам, поэтому # можно тоже добавить в класс символов ненужных в адрес.
например
<?
'~<a [^>]*\bhref\s*=\s*["\']?((?!https?://)[^ "#\'>]*)~'
|
"\s*=\s*" потомучто в тегах перед знаком "=" и после него допускаются пробельные символы,
здесь подмаска захватит ссылку "#xxxxxx" как пустую строку, поскольку "[^ "#\'>]*"
уже с "*" а не "+"
и модификатор "s" был не нужен , поскольку в выражении небыло не одной "." которая могла-бы не совпасть с переводом строки | |
|
|
|