Mengambil atribut href dari elemen A.


114

Mencoba menemukan tautan pada suatu halaman.

regex saya adalah:

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

tapi sepertinya gagal

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

Bagaimana cara mengubah ekspresi reguler saya untuk menangani href yang tidak ditempatkan pertama dalam tag?

Jawaban:


208

Regex yang andal untuk HTML itu sulit . Berikut ini cara melakukannya dengan DOM :

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

Di atas akan mencari dan mengeluarkan "outerHTML" dari semua Aelemen di$html string.

Untuk mendapatkan semua nilai teks dari node, Anda melakukannya

echo $node->nodeValue; 

Untuk memeriksa apakah hrefatribut tersebut ada, Anda dapat melakukannya

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

Untuk mendapatkan yang hrefatribut Anda akan melakukan

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

Untuk mengubah yang hrefatribut Anda akan melakukan

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

Untuk menghapus satu hrefatribut yang akan Anda lakukan

$node->removeAttribute('href'); 

Anda juga dapat menanyakan hrefatribut secara langsung dengan 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
}

Lihat juga:

Di samping itu: Saya yakin ini adalah duplikat dan Anda dapat menemukan jawabannya di suatu tempat di sini


Regex andal untuk parsing HTML secara inheren tidak mungkin dilakukan bahkan karena HTML bukan bahasa biasa.
Asciiom

19

Saya setuju dengan Gordon, Anda HARUS menggunakan pengurai HTML untuk mengurai HTML. Tetapi jika Anda benar-benar menginginkan regex, Anda dapat mencoba yang ini:

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

Ini cocok <adi awal string, diikuti dengan sejumlah karakter apa pun (tidak serakah) .*?lalu href=diikuti dengan tautan yang dikelilingi oleh salah satu "atau'

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

Keluaran:

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

hanya untuk info: jika kita mencari dalam teks yang mengandung banyak elemen daripada ekspresi (. *?) salah
Michal - wereda-net

5

Pola yang ingin Anda cari adalah pola tautan tautan, seperti (sesuatu):

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

1
Bagaimana jika jangkar memiliki lebih banyak atribut?
funerr

3

kenapa kamu tidak cocok saja

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

?>

kemudian

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

yang berhasil. Saya baru saja melepas kawat gigi penangkap pertama.


2
saya merekomendasikan untuk menggunakan preg_match_all("/<a.*?href\s*=\s*['\"](.*?)['\"]/", $str, $res, PREG_SET_ORDER);untuk menangkap dengan benar semua nilai href dalam menggunakanforeach($res as $key => $val){echo $val[1]}
Ignacio Bustos

3

Untuk orang yang masih belum mendapatkan solusi dengan sangat mudah dan cepat menggunakan SimpleXML

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

Ini bekerja untuk saya


2

Saya tidak yakin apa yang Anda coba lakukan di sini, tetapi jika Anda mencoba memvalidasi tautan, lihat filter_var () PHP

Jika Anda benar-benar perlu menggunakan ekspresi reguler, periksa alat ini, ini mungkin membantu: http://regex.larsolavtorvik.com/


2

Menggunakan regex Anda, saya memodifikasinya sedikit agar sesuai dengan kebutuhan Anda.

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

Saya pribadi menyarankan Anda menggunakan HTML Parser

EDIT: Diuji


menggunakan myregextester.com - maaf, tidak menemukan tautan
bergin

dikatakan: TIDAK ADA PERTANDINGAN. PERIKSA PENGOLAHAN BATAS.
bergin

Bisakah Anda memberi tahu saya teks yang akan dicocokkan? Saya menggunakan:<a title="this" href="that">what?</a>
Ruel

1

Tes cepat: <a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a> tampaknya berhasil, dengan kecocokan pertama adalah "atau ', yang kedua adalah' nilai 'href' itu ', dan yang ketiga adalah' apa? '.

Alasan saya meninggalkan kecocokan pertama "/ 'di sana adalah karena Anda dapat menggunakannya untuk mereferensikannya nanti untuk penutupan" /' sehingga sama.

Lihat contoh langsung di: http://www.rubular.com/r/jsKyK2b6do


1
@bergin sebutkan, apa yang tidak berhasil? Saya mendapatkan nilai yang tepat dari href di HTML pengujian Anda. Apa yang Anda harapkan bahwa ini tidak berhasil? Saya melihat Anda menggunakan situs yang berbeda untuk pengujian, di sana saya juga berhasil mendapatkan nilai 'href' dari contoh Anda. myregextester.com/?r=d966dd6b
CharlesLeaf

0

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

Ini diuji dan mengambil semua tag dari kode html apa pun.


0

Berikut ini bekerja untuk saya dan mengembalikan keduanya hrefdan valuedari tag jangkar.

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

Array multidimensi yang disebut $urlssekarang berisi sub-array asosiatif yang mudah digunakan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.