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


114

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

私の正規表現は:

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

しかし失敗するようです

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

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

回答:


208

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'); 

XPathを使用してhref属性を直接クエリすることもできます

$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 2013年

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


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]}
Ignacio Bustos 2013年

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>1つ目の一致が "または"、2番目は "href"値、 "3つ目"、3つ目は "何ですか?"でトリックを実行するようです。

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

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


1
@berginを指定してください、何が機能しませんか?テストHTMLのhrefから正確な値を取得します。これが機能しないことを何を期待していますか?テストに別のサイトを使用しているようですが、サンプルから 'href'値も正常に取得されています。myregextester.com/?r=d966dd6b
CharlesLeaf

0

preg_match_all( "/(] >)(。 )(</ A)/?"、$内容、$ impmatches、PREG_SET_ORDER)。

それはテストされ、任意のhtmlコードからすべてのタグをフェッチします。


0

次は私のために働いており、アンカータグ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は、使いやすい連想サブ配列が含まれています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.