Bir A öğesinin href özniteliğini kapma


114

Bir sayfadaki bağlantıları bulmaya çalışıyorum.

normal ifadem:

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

ama başarısız görünüyor

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

Normal ifademi, a etiketinde ilk sırada yer almayan href ile ilgilenecek şekilde nasıl değiştirebilirim?

Yanıtlar:


208

HTML için güvenilir Regex zordur . Bunu DOM ile şu şekilde yapabilirsiniz :

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

Yukarıdakiler , dizedeki tüm öğelerin "dış HTML" ni bulur ve verir .A$html

To olsun düğümün tüm metin değerlerini, yapmanız

echo $node->nodeValue; 

To kontrol eğer hrefnitelik Yapabileceğiniz var

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

To olsunhref yapacağın niteliği

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

To değiştirmekhref özelliğini yapacağın

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

To kaldırmakhref yapacağın niteliği

$node->removeAttribute('href'); 

hrefÖzniteliği doğrudan XPath ile de sorgulayabilirsiniz.

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

Ayrıca bkz:

Bir yan notta: Bunun bir kopya olduğuna eminim ve cevabı burada bir yerde bulabilirsiniz


HTML'yi ayrıştırmak için güvenilir normal ifade, HTML normal bir dil olmadığı için doğası gereği imkansızdır.
Asciiom

19

Gordon'a katılıyorum, HTML'yi ayrıştırmak için bir HTML ayrıştırıcı kullanmanız GEREKİR. Ancak gerçekten bir normal ifade istiyorsanız, bunu deneyebilirsiniz:

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

Bu <a, dizenin başlangıcında eşleşir , ardından herhangi bir sayıda karakter (açgözlü olmayan) ve .*?ardından href=ya da "veya'

$str = '<a title="this" href="that">what?</a>';
preg_match('/^<a.*?href=(["\'])(.*?)\1.*$/', $str, $m);
var_dump($m);

Çıktı:

array(3) {
  [0]=>
  string(37) "<a title="this" href="that">what?</a>"
  [1]=>
  string(1) """
  [2]=>
  string(4) "that"
}

sadece bilgi için:
İfadeden

5

Aramak istediğiniz model, (bir şey) gibi bağlantı bağlantı kalıbı olacaktır:

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

1
Ya çapanın daha fazla özelliği varsa?
funerr

3

neden sadece eşleşmiyorsun

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

?>

sonra

$ php test.php
array(2) {
  [0]=>
  array(1) {
    [0]=>
    string(27) "<a title="this" href="that""
  }
  [1]=>
  array(1) {
    [0]=>
    string(4) "that"
  }
}

hangi çalışır. İlk yakalama tellerini yeni çıkardım.


2
preg_match_all("/<a.*?href\s*=\s*['\"](.*?)['\"]/", $str, $res, PREG_SET_ORDER);Kullanırken tüm href değerlerini doğru bir şekilde yakalamak için kullanmanızı tavsiye ederimforeach($res as $key => $val){echo $val[1]}
Ignacio Bustos

3

SimpleXML kullanarak çözümleri hala çok kolay ve hızlı alamayanlar için

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

Benim için çalışıyor


2

Burada ne yapmaya çalıştığınızdan emin değilim, ancak bağlantıyı doğrulamaya çalışıyorsanız, o zaman PHP'nin filter_var () öğesine bakın

Eğer gerçekten bir düzenli ifade kullanmanız gerekiyorsa, bu araca bir göz atın, yardımcı olabilir: http://regex.larsolavtorvik.com/


2

Normal ifadenizi kullanarak ihtiyacınıza uyacak şekilde biraz değiştirdim.

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

Ben şahsen bir HTML Ayrıştırıcı kullanmanızı öneririm

DÜZENLEME: Test edildi


myregextester.com'u kullanıyor - üzgünüm, bağlantıları bulamıyor
bergin

diyor ki: MAÇ YOK. DELIMITER COLLISION'I KONTROL EDİN.
bergin

Lütfen bana eşleşecek metni söyler misin? Ben kullanıyorum:<a title="this" href="that">what?</a>
Ruel

1

Hızlı test: <a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a> İlk maç "veya", ikincisi "href" değeri "bu" ve üçüncüsü "ne?" İle hile yapıyor gibi görünüyor.

"/" İlk eşleşmesini burada bırakmamın nedeni, onu daha sonra "/" kapanışı için geri referans yapmak için kullanabilmenizdir, yani aynıdır.

Canlı örneğe bakın: http://www.rubular.com/r/jsKyK2b6do


1
@bergin lütfen belirtin, ne çalışmıyor? Test HTML'nizdeki href'den tam değeri alıyorum. Bunun yapmamasını bekliyorsunuz? Test için farklı bir site kullandığınızı görüyorum, orada da örneğinizden 'href' değerini başarıyla alıyorum. myregextester.com/?r=d966dd6b
CharlesLeaf

0

preg_match_all ("/ (] >) (. ?) (</ a) /", $ içerikler, $ impmatches, PREG_SET_ORDER);

Test edilir ve herhangi bir html kodundan tüm bir etiketi alır.


0

Aşağıdakiler benim için çalışıyor ve hem hrefve hem valuede bağlantı etiketini döndürüyor .

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]
        );
    }
}

Adlı çok boyutlu dizi $urls, artık kullanımı kolay ilişkilendirilebilir alt dizileri içerir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.