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.