Захват атрибута href элемента A
Пытаюсь найти ссылки на странице.
Мое регулярное выражение:
/<a\s[^>]*href=(\"\'??)([^\"\' >]*?)[^>]*>(.*)<\/a>/
Но, похоже, терпит неудачу в
<a title="this" href="that">what?</a>
Как бы я изменил свое регулярное выражение, чтобы иметь дело с href, не помещенным первым в теге a?
9 answers
Надежные регулярные выражения для HTML являются сложными. Вот как это сделать с DOM:
$dom = new DOMDocument;
$dom->loadHTML($html);
foreach ($dom->getElementsByTagName('a') as $node) {
echo $dom->saveHtml($node), PHP_EOL;
}
Вышеизложенное позволит найти и вывести "outerHTML" всех A
элементов в строке $html
.
Чтобы получить все текстовые значения узла, вы делаете
echo $node->nodeValue;
К проверьте , существует ли атрибут href
, вы можете сделать
echo $node->hasAttribute( 'href' );
Для получить атрибут href
, который вы бы сделали
echo $node->getAttribute( 'href' );
На изменить атрибут href
, который вы бы сделали
$node->setAttribute('href', 'something else');
Чтобы удалить атрибут href
, который вы бы сделали
$node->removeAttribute('href');
Вы также можете запросить атрибут href
напрямую с помощью XPath
$dom = new DOMDocument;
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//a/@href');
foreach($nodes as $href) {
echo $href->nodeValue; // echo current attribute value
$href->nodeValue = 'new value'; // set new attribute value
$href->parentNode->removeAttribute('href'); // remove attribute
}
Также смотрите:
В примечании: Я уверен, что это дубликат, и вы можете найти ответ где-нибудь здесь
Я согласен с Гордоном, вы ДОЛЖНЫ использовать синтаксический анализатор HTML для анализа HTML. Но если вам действительно нужно регулярное выражение, вы можете попробовать следующее:
/^<a.*?href=(["\'])(.*?)\1.*$/
Это соответствует <a
в начале строки, за которым следует любое число любых символов (не жадных) .*?
, затем href=
, за которым следует ссылка, окруженная либо "
, либо '
$str = '<a title="this" href="that">what?</a>';
preg_match('/^<a.*?href=(["\'])(.*?)\1.*$/', $str, $m);
var_dump($m);
Вывод:
array(3) {
[0]=>
string(37) "<a title="this" href="that">what?</a>"
[1]=>
string(1) """
[2]=>
string(4) "that"
}
Шаблон, который вы хотите найти, будет шаблоном привязки ссылки, например (что-то):
$regex_pattern = "/<a href=\"(.*)\">(.*)<\/a>/";
Почему бы вам просто не сопоставить
"<a.*?href\s*=\s*['"](.*?)['"]"
<?php
$str = '<a title="this" href="that">what?</a>';
$res = array();
preg_match_all("/<a.*?href\s*=\s*['\"](.*?)['\"]/", $str, $res);
var_dump($res);
?>
Затем
$ php test.php
array(2) {
[0]=>
array(1) {
[0]=>
string(27) "<a title="this" href="that""
}
[1]=>
array(1) {
[0]=>
string(4) "that"
}
}
Который работает. Я только что удалил первые скобки захвата.
Я не уверен, что вы пытаетесь здесь сделать, но если вы пытаетесь проверить ссылку, то посмотрите на PHP filter_var()
Если вам действительно нужно использовать регулярное выражение, то ознакомьтесь с этим инструментом, он может помочь: http://regex.larsolavtorvik.com/
Используя ваше регулярное выражение, я немного изменил его в соответствии с вашими потребностями.
<a.*?href=("|')(.*?)("|').*?>(.*)<\/a>
Я лично предлагаю вам использовать Синтаксический анализатор HTML
РЕДАКТИРОВАТЬ: Проверено
Для тех, кто все еще не получает решения очень легко и быстро с помощью SimpleXML
$a = new SimpleXMLElement('<a href="www.something.com">Click here</a>');
echo $a['href']; // will echo www.something.com
Это работает на меня
Быстрый тест: <a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a>
, похоже, делает свое дело, при этом 1-е совпадение "или", второе значение "href" "это", а третье "что?".
Причина, по которой я оставил первое совпадение "/", заключается в том, что вы можете использовать его для обратной ссылки позже для закрытия "/"так что это то же самое.
Смотрите живой пример на: http://www.rubular.com/r/jsKyK2b6do
Прег_матч_алл("/(]>)(.?)( a)/", $содержимое, $несоответствия, PREG_SET_ORDER);
Он протестирован и извлекает все теги из любого html-кода.