抓取A元素的href属性


114

试图在页面上找到链接。

我的正则表达式是:

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

但似乎失败了

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

我该如何更改我的正则表达式以处理未置于a标签首位的href?

Answers:


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

您也可以href直接使用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
}

另请参阅:

旁注:我确定这是重复的,您可以在这里的某个地方找到答案


即使HTML不是常规语言,用于解析HTML的可靠正则表达式本质上也是不可能的。
Asciiom

19

我同意Gordon,您必须使用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"
}

只是为了提供信息:如果我们在包含许多元素的文本中搜索,而表达式(。*?)是错误的
Michal-areda-net 2014年

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-对不起,找不到链接
卑尔根

它说:没有比赛。检查定界符冲突。
卑尔根2010年

你能告诉我要匹配的文字吗?我使用:<a title="this" href="that">what?</a>
Ruel

1

快速测试: <a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a>似乎可以解决问题,第一个匹配为“或”,第二个为“ href”值“ that”,第三个为“ what?”。

我之所以将第一个匹配项“ /”留在其中的原因是,您可以稍后用它反向引用以结束“ /”,因此它是相同的。

参见以下示例:http : //www.rubular.com/r/jsKyK2b6do


1
@bergin请指定,什么不起作用?我从您的测试HTML中的href获得确切的值。您期望这不会做什么?我看到您使用其他站点进行测试,从您的示例中我也成功获得了“ href”值。myregextester.com/?r=d966dd6b
CharlesLeaf 2010年


0

以下内容对我有用,href并且同时返回和value的锚标记。

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现在,称为的多维数组包含易于使用的关联子数组。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.