Я пытаюсь найти ссылки на странице. Вот мое регулярное выражение:
/<a\s[^>]*href=(\"\'??)([^\"\' >]*?)[^>]*>(.*)<\/a>/
но, похоже, оно не работает:
<a title="this" href="that">what?</a>
Как мне изменить свое регулярное выражение, чтобы получить href, который не прописан первым в теге?
Ответ 1
Создать надежное регулярное выражение для HTML — сложная задача. Вот как это можно сделать с помощью DOM:
$dom = new DOMDocument;
$dom->loadHTML($html);
foreach ($dom->getElementsByTagName('a') as $node) {
echo $dom->saveHtml($node), PHP_EOL;
}
Вышеупомянутый код найдет и выведет "externalHTML" для всех тегов «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 значения текущего атрибута
$href->nodeValue = 'new value'; // установка нового значения
$href->parentNode->removeAttribute('href'); // удаление атрибута
}
Ответ 2
Вы должны использовать парсер для синтаксического анализа 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"
}
Ответ 3
Почему бы вам просто не сопоставить:
"<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"
}
}
Ответ 4
Далее работает для меня и возвращается как href и value из тега <a>.
preg_match_all("'\<a.*?href=\"(.*?)\".*?\>(.*?)\<\/a\>'si", $html, $match);
if($match) {
foreach($match[0] as $k => $e) {
$urls[] = array(
'anchor' => $e,
'href' => $match[1][$k],
'value' => $match[2][$k]
);
}
}
Многомерный массив под названием $urls теперь содержит ассоциативные подмассивы, которые легко использовать.
Web