Захоплення атрибута href елемента A


114

Намагання знайти посилання на сторінці.

мій регулярний вираз:

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

але, здається, не вдається

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

Як я можу змінити свій регулярний вираз, щоб мати справу з href, не розміщеним першим у тезі?

Відповіді:


208

Надійний Regex для HTML важкий . Ось як це зробити з DOM :

$dom = new DOMDocument;
$dom->loadHTML($html);
foreach ($dom->getElementsByTagName('a') as $node) {
    echo $dom->saveHtml($node), PHP_EOL;
}

Вищезазначене знайде та виведе " зовнішній HTML" всіх 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 не є звичайною мовою.
Asciiom

19

Я погоджуюся з Гордоном, ви ОБОВ'ЯЗКОВИ використовувати 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"
}

лише для інформації: якщо ми шукаємо текст, що містить багато елементів, ніж вираз (. *?), помиляється
Michal - wereda-net

5

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

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

1
Що робити, якщо якір має більше атрибутів?
funerr

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("/<a.*?href\s*=\s*['\"](.*?)['\"]/", $str, $res, PREG_SET_ORDER);для того, щоб правильно використати всі значення href у використанніforeach($res as $key => $val){echo $val[1]}
Ігнасіо Бустос

3

Для того, хто досі не отримує рішення дуже легко та швидко за допомогою SimpleXML

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

Це працює для мене


2

Я не впевнений, що ви намагаєтеся зробити тут, але якщо ви намагаєтесь перевірити посилання, то подивіться на PHP filter_var ()

Якщо вам дійсно потрібно використовувати регулярний вираз, перегляньте цей інструмент, він може допомогти: http://regex.larsolavtorvik.com/


2

Використовуючи ваш регулярний вираз, я трохи змінив його відповідно до ваших потреб.

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

Я особисто пропоную вам скористатися HTML-аналізатором

РЕДАКТУВАННЯ: Випробувано


за допомогою myregextester.com - вибачте, не знайдіть посилання
bergin

там сказано: НЕ МАТЧІВ. ПЕРЕВІРИТИСЯ НА КОЛІЗАЦІЮ ДЕЛІМИТРА
Бергін

Скажіть, будь ласка, текст, який потрібно відповідати? Я використовую:<a title="this" href="that">what?</a>
Ruel

1

Швидкий тест: <a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a>начебто, робиться хитрість: перший матч - це "або", другий - значення "href", що ", а третє -" що? ".

Причиною того, що я залишив перший збіг "/", є те, що ви можете використовувати його, щоб повернути його пізніше для закриття "/", так що це те саме.

Дивіться приклад на веб-сайті : http://www.rubular.com/r/jsKyK2b6do


1
@bergin, будь ласка, вкажіть, що не працює? Я отримую точне значення від href у вашому тестовому HTML. Що ви очікуєте, що це не зробить? Я бачу, що ви використовуєте інший сайт для тестування, там я також отримую значення 'href' з вашого прикладу. myregextester.com/?r=d966dd6b
CharlesLeaf

0

preg_match_all ("/ (] >) ( ?) (</ a) /", $ content, $ impmatches, PREG_SET_ORDER);

Він тестується, і він отримує весь тег з будь-якого html-коду.


0

Наступне працює для мене і повертає 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містить тепер асоціативні підмасиви, які прості у використанні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.