Получение атрибута href элемента A - PullRequest
111 голосов
/ 29 сентября 2010

Попытка найти ссылки на странице.

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

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

, но, похоже, не работает на

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

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

Ответы [ 10 ]

205 голосов
/ 29 сентября 2010

Надежные регулярные выражения для 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, который вы'do

$node->setAttribute('href', 'something else');

To удалить атрибут 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
}

См. Также:

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

17 голосов
/ 29 сентября 2010

Я согласен с Гордоном, вы ДОЛЖНЫ использовать анализатор 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"
}
5 голосов
/ 29 сентября 2010

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

$regex_pattern = "/<a href=\"(.*)\">(.*)<\/a>/";
3 голосов
/ 26 августа 2016

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

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

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

3 голосов
/ 29 сентября 2010

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

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

, что работает.Я только что снял первые скобы захвата.

2 голосов
/ 29 сентября 2010

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

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

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

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

2 голосов
/ 29 сентября 2010

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

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

1 голос
/ 29 сентября 2010

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

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

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

0 голосов
/ 22 января 2019

Следующее работает для меня и возвращает и href, и value тега привязки.

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 содержит теперь ассоциативные подмассивы, которые легкоиспользовать.

0 голосов
/ 06 июля 2016

preg_match_all ("/ (] >) (. ?) (</ A) /", $ content, $ impmatches, PREG_SET_ORDER); </p>

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...