web-dev-qa-db-ja.com

A要素のhref属性を取得する

ページ上のリンクを見つけようとしています。

私の正規表現は:

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

しかしで失敗するようです

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

Aタグの最初に配置されていないhrefを処理するように正規表現を変更するにはどうすればよいですか?

112
bergin

HTMLの信頼できる正規表現は難しいDOM でそれを行う方法は次のとおりです。

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

上記は、$html文字列内のすべてのA要素の "outerHTML" を見つけて出力します。

getノードのすべてのテキスト値に、あなたは

echo $node->nodeValue; 

checkhref属性が存在する場合、実行できます

echo $node->hasAttribute( 'href' );

getするhref属性

echo $node->getAttribute( 'href' );

changeするhref属性

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

removeするhref属性

$node->removeAttribute('href'); 

XPathhref属性を直接クエリすることもできます

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

参照:

副注:これは重複していると確信しています ここのどこかに答えを見つけます

206
Gordon

Gordonに同意します。HTMLを解析するにはHTMLパーサーを使用する必要があります。しかし、本当に正規表現が必要な場合は、これを試すことができます:

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

これは、文字列の先頭で<aに一致し、任意の数のchar(貪欲でない).*?が続き、その後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"
}
18
Toto

探したいパターンは、(次のような)リンクアンカーパターンです。

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

SimpleXMLを使用してソリューションを非常に簡単かつ迅速に取得できない場合

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

私のために働く

3
Milan Malani

なぜあなたはちょうど一致しないのですか

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

ここで何をしようとしているのかわかりませんが、リンクを検証しようとしている場合は、PHPのfilter_var()を見てください

本当に正規表現を使用する必要がある場合は、このツールを確認してください。 http://regex.larsolavtorvik.com/

2
Adam

正規表現を使用して、必要に応じて少し変更しました。

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

個人的に HTMLパーサー を使用することをお勧めします

編集:テスト済み

2
Ruel

クイックテスト:<a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a>はトリックを実行するようで、最初の一致は "または"、2番目は 'href'値、それは、3番目は 'what?'です。

「/」の最初の一致をそこに残した理由は、それを使用して後で「/」を閉じるために後方参照することができるため、同じです。

次のライブ例をご覧ください: http://www.rubular.com/r/jsKyK2b6do

1
CharlesLeaf

preg_match_all( "/(]>)(.?)(</ a)/"、$ contents、$ impmatches、PREG_SET_ORDER);

テストされ、すべてのHTMLコードからすべてのタグを取得します。

0
Ravi Prakash

以下は私のために働いており、アンカータグのhrefvalueの両方を返します。

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
Meloman