2010-09-29 2 views
106

Попытка найти ссылки на странице.Схват атрибута href элемента A

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

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

, но, кажется, терпят неудачу в

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

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

ответ

193

Reliable Regex for HTML are difficult. Вот как сделать это с 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 
} 

Также см:

На заметка на полях: Я уверен, что это дубликат, и вы можете find the answer somewhere in here

+0

Надежное регулярное выражение для синтаксического анализа HTML по своей сути невозможно даже, поскольку HTML не является обычным языком. – Asciiom

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

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

+2

я рекомендую использовать 'preg_match_all ("/ <а. *? HREF \ с * = \ s * [ '\"] (. *?) ['\ "] /", $ str, $ res, PREG_SET_ORDER); 'чтобы правильно уловить все значения href при использовании' foreach ($ res as $ key => $ val) {echo $ val [1]} ' –

+0

@IgnacioBustos отлично работал – mostafaznv

5

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

$regex_pattern = "/<a href=\"(.*)\">(.*)<\/a>/"; 
+1

Что делать, если у якоря больше атрибутов? – funerr

1

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

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

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

+0

не работает, извините – bergin

+1

@bergin уточните, что не работает? Я получаю точное значение из href в тестовом HTML. Что вы ожидаете, что этого не происходит? Я вижу, что вы используете другой сайт для тестирования, я также получаю «href» значение успешно из вашего примера. http://www.myregextester.com/?r=d966dd6b – CharlesLeaf

2

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

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

2

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

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

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

EDIT: Испытано

+0

с помощью myregextester.com - извините, не нашел ссылки – bergin

+0

@bergin, Привет, я изменил свой ответ, и он работает сейчас. – Ruel

+0

в нем говорится: НЕТ МАТЧА. ПРОВЕРЬТЕ ЗАКЛЮЧЕНИЕ ДОЛЖИТЕЛЕЙ. – bergin

16

Я согласен с Гордоном, вы должны использовать 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" 
} 
+0

только для информации: если мы ищем в тексте, содержащем много элементов, чем выражение (. *?) Неправильно –

0

preg_match_all ("/ (] >) (. ?) (</а) /», $ содержание, $ impmatches, PREG_SET_ORDER);

Испытано и извлечь все тег из любого HTML кода

2

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

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

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