Захват атрибута href элемента A


Пытаюсь найти ссылки на странице.

Мое регулярное выражение:

/<a\s[^>]*href=(\"\'??)([^\"\' >]*?)[^>]*>(.*)<\/a>/

Но, похоже, терпит неудачу в

<a title="this" href="that">what?</a>

Как бы я изменил свое регулярное выражение, чтобы иметь дело с href, не помещенным первым в теге a?

 107
Author: bergin, 2010-09-29

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
}

Также смотрите:

В примечании: Я уверен, что это дубликат, и вы можете найти ответ где-нибудь здесь

 197
Author: Gordon, 2017-05-23 12:10:35

Я согласен с Гордоном, вы ДОЛЖНЫ использовать синтаксический анализатор 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"
}
 16
Author: Toto, 2010-09-29 11:43:02

Шаблон, который вы хотите найти, будет шаблоном привязки ссылки, например (что-то):

$regex_pattern = "/<a href=\"(.*)\">(.*)<\/a>/";
 5
Author: pltvs, 2010-09-29 10:22:23

Почему бы вам просто не сопоставить

"<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"
  }
}

Который работает. Я только что удалил первые скобки захвата.

 3
Author: Aif, 2010-09-29 10:33:36

Я не уверен, что вы пытаетесь здесь сделать, но если вы пытаетесь проверить ссылку, то посмотрите на PHP filter_var()

Если вам действительно нужно использовать регулярное выражение, то ознакомьтесь с этим инструментом, он может помочь: http://regex.larsolavtorvik.com/

 2
Author: Adam, 2010-09-29 10:25:32

Используя ваше регулярное выражение, я немного изменил его в соответствии с вашими потребностями.

<a.*?href=("|')(.*?)("|').*?>(.*)<\/a>

Я лично предлагаю вам использовать Синтаксический анализатор HTML

РЕДАКТИРОВАТЬ: Проверено

 2
Author: Ruel, 2010-09-29 10:33:11

Для тех, кто все еще не получает решения очень легко и быстро с помощью SimpleXML

$a = new SimpleXMLElement('<a href="www.something.com">Click here</a>');
echo $a['href']; // will echo www.something.com

Это работает на меня

 2
Author: Milan Malani, 2016-08-26 11:17:59

Быстрый тест: <a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a>, похоже, делает свое дело, при этом 1-е совпадение "или", второе значение "href" "это", а третье "что?".

Причина, по которой я оставил первое совпадение "/", заключается в том, что вы можете использовать его для обратной ссылки позже для закрытия "/"так что это то же самое.

Смотрите живой пример на: http://www.rubular.com/r/jsKyK2b6do

 1
Author: CharlesLeaf, 2010-09-29 10:23:22

Прег_матч_алл("/(]>)(.?)( a)/", $содержимое, $несоответствия, PREG_SET_ORDER);

Он протестирован и извлекает все теги из любого html-кода.

 0
Author: Ravi Prakash, 2016-07-06 05:23:10