Lấy thuộc tính href của một phần tử A


114

Cố gắng tìm các liên kết trên một trang.

regex của tôi là:

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

nhưng dường như thất bại ở

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

Làm cách nào để thay đổi regex của mình để đối phó với href không được đặt đầu tiên trong thẻ?

Câu trả lời:


208

Regex đáng tin cậy cho HTML rất khó . Đây là cách thực hiện với DOM :

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

Ở trên sẽ tìm và xuất ra "externalHTML" của tất cả các Aphần tử trong $htmlchuỗi.

Để nhận tất cả các giá trị văn bản của nút, bạn làm

echo $node->nodeValue; 

Để kiểm tra nếu hrefthuộc tính tồn tại bạn có thể làm

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

Để có được các hrefthuộc tính bạn muốn làm

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

Để thay đổi các hrefthuộc tính bạn muốn làm

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

Để loại bỏ các hrefthuộc tính bạn muốn làm

$node->removeAttribute('href'); 

Bạn cũng có thể truy vấn hreftrực tiếp thuộc tính bằng 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
}

Cũng thấy:

Ghi chú bên lề: Tôi chắc chắn rằng đây là một bản sao và bạn có thể tìm thấy câu trả lời ở đâu đó tại đây


Regex đáng tin cậy để phân tích cú pháp HTML vốn dĩ là không thể ngay cả khi HTML không phải là một ngôn ngữ thông thường.
Asciiom

19

Tôi đồng ý với Gordon, bạn PHẢI sử dụng trình phân tích cú pháp HTML để phân tích cú pháp HTML. Nhưng nếu bạn thực sự muốn có một regex, bạn có thể thử cái này:

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

Điều này khớp <aở đầu chuỗi, theo sau là một số bất kỳ của bất kỳ ký tự nào (không tham lam), .*?sau đó href=là liên kết được bao quanh bởi "hoặc'

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

Đầu ra:

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

chỉ để biết: nếu chúng ta tìm kiếm trong một văn bản có chứa nhiều yếu tố một hơn biểu thức (.? *) là sai
Michal - wereda-net

5

Mẫu bạn muốn tìm sẽ là mẫu neo liên kết, như (một cái gì đó):

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

1
Điều gì sẽ xảy ra nếu neo có nhiều thuộc tính hơn?
funerr

3

tại sao bạn không chỉ phù hợp

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

?>

sau đó

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

cái nào hoạt động. Tôi vừa tháo niềng răng chụp đầu tiên.


2
tôi khuyên bạn nên sử dụng preg_match_all("/<a.*?href\s*=\s*['\"](.*?)['\"]/", $str, $res, PREG_SET_ORDER);để nắm bắt một cách chính xác tất cả các giá trị href trong việc sử dụngforeach($res as $key => $val){echo $val[1]}
Ignacio Bustos

3

Đối với những người vẫn chưa nhận được các giải pháp rất dễ dàng và nhanh chóng bằng cách sử dụng SimpleXML

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

Nó làm việc cho tôi


2

Tôi không chắc bạn đang cố gắng làm gì ở đây, nhưng nếu bạn đang cố gắng xác thực liên kết thì hãy xem filter_var () của PHP

Nếu bạn thực sự cần sử dụng biểu thức chính quy thì hãy xem công cụ này, nó có thể hữu ích: http://regex.larsolavtorvik.com/


2

Sử dụng regex của bạn, tôi đã sửa đổi nó một chút để phù hợp với nhu cầu của bạn.

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

Cá nhân tôi khuyên bạn nên sử dụng Trình phân tích cú pháp HTML

CHỈNH SỬA: Đã kiểm tra


sử dụng myregextester.com - xin lỗi, doesnt tìm các liên kết
Bergin

nó nói: KHÔNG CÓ TRẬN ĐẤU. KIỂM TRA LƯU LƯỢNG XÓA.
bergin

Bạn có thể vui lòng cho tôi biết văn bản để phù hợp? Tôi sử dụng:<a title="this" href="that">what?</a>
Ruel

1

Kiểm tra nhanh: <a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a>có vẻ là một mẹo nhỏ, với kết quả phù hợp đầu tiên là "hoặc", so khớp thứ hai là 'href' giá trị 'that' và kết quả thứ ba là 'what?'.

Lý do tôi để kết quả khớp đầu tiên của "/ 'ở đó là bạn có thể sử dụng nó để tham chiếu ngược lại sau này cho việc đóng" /' nên nó giống nhau.

Xem ví dụ trực tiếp trên: http://www.rubular.com/r/jsKyK2b6do


1
@bergin vui lòng chỉ rõ, điều gì không hoạt động? Tôi nhận được giá trị chính xác từ href trong HTML thử nghiệm của bạn. Bạn đang mong đợi điều gì mà điều này không làm được? Tôi thấy bạn sử dụng một trang web khác để thử nghiệm, ở đó tôi cũng nhận được giá trị 'href' thành công từ ví dụ của bạn. myregextester.com/?r=d966dd6b
CharlesLeaf

0

preg_match_all ("/ (] >) (. ?) (</ a) /", $ nội dung, $ impmatches, PREG_SET_ORDER);

Nó được thử nghiệm và tìm nạp tất cả thẻ từ bất kỳ mã html nào.


0

Phần sau hoạt động đối với tôi và trả về cả hrefvaluecủa thẻ liên kết.

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

Mảng đa chiều được gọi $urlshiện chứa các mảng con liên kết rất dễ sử dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.