【发布时间】:2011-04-18 18:03:24
【问题描述】:
试图在页面上找到链接。
我的正则表达式是:
/<a\s[^>]*href=(\"\'??)([^\"\' >]*?)[^>]*>(.*)<\/a>/
但似乎失败了
<a title="this" href="that">what?</a>
我将如何更改我的正则表达式以处理未放在 a 标记中的 href?
【问题讨论】:
试图在页面上找到链接。
我的正则表达式是:
/<a\s[^>]*href=(\"\'??)([^\"\' >]*?)[^>]*>(.*)<\/a>/
但似乎失败了
<a title="this" href="that">what?</a>
我将如何更改我的正则表达式以处理未放在 a 标记中的 href?
【问题讨论】:
Reliable Regex for HTML are difficult。以下是使用DOM 的方法:
$dom = new DOMDocument;
$dom->loadHTML($html);
foreach ($dom->getElementsByTagName('a') as $node) {
echo $dom->saveHtml($node), PHP_EOL;
}
上面将找到并输出$html 字符串中所有A 元素的"outerHTML"。
要获取节点的所有文本值,您可以这样做
echo $node->nodeValue;
要检查href 属性是否存在,您可以这样做
echo $node->hasAttribute( 'href' );
要获取你会做的href属性
echo $node->getAttribute( 'href' );
更改你会做的href属性
$node->setAttribute('href', 'something else');
删除你会做的href属性
$node->removeAttribute('href');
也可以直接用XPath查询href属性
$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
}
另见:
附注:我确定这是重复的,您可以find the answer somewhere in here
【讨论】:
我同意 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"
}
【讨论】:
您要查找的模式是链接锚模式,例如(某物):
$regex_pattern = "/<a href=\"(.*)\">(.*)<\/a>/";
【讨论】:
你为什么不直接匹配
"<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"
}
}
有效。我刚刚删除了第一个捕获括号。
【讨论】:
preg_match_all("/<a.*?href\s*=\s*['\"](.*?)['\"]/", $str, $res, PREG_SET_ORDER);,以便在使用foreach($res as $key => $val){echo $val[1]}时正确捕获所有href值
对于仍然无法使用 SimpleXML 轻松快速地获得解决方案的人
$a = new SimpleXMLElement('<a href="www.something.com">Click here</a>');
echo $a['href']; // will echo www.something.com
它对我有用
【讨论】:
快速测试:<a\s+[^>]*href=(\"\'??)([^\1]+)(?:\1)>(.*)<\/a> 似乎可以解决问题,第一个匹配是 " 或 ',第二个匹配 'href' 值 'that',第三个匹配 'what?'。
我将“/”的第一个匹配项留在其中的原因是您可以稍后使用它来反向引用它以关闭“/”,所以它是相同的。
【讨论】:
我不确定您在这里要做什么,但如果您要验证链接,请查看 PHP 的 filter_var()
如果您确实需要使用正则表达式,请查看此工具,它可能会有所帮助: http://regex.larsolavtorvik.com/
【讨论】:
使用您的正则表达式,我对其进行了一些修改以满足您的需要。
<a.*?href=("|')(.*?)("|').*?>(.*)<\/a>
我个人建议你使用HTML Parser
编辑:测试
【讨论】:
<a title="this" href="that">what?</a>
< 是起始分隔符,> 是结束分隔符(当然这些字符出现在模式中,所以你有“冲突”。
以下内容对我有用,并返回锚标记的 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 的多维数组现在包含易于使用的关联子数组。
【讨论】:
/,但由于您的模式使用了/,我可能会推荐~。因为分隔符不是/,所以您不需要在模式中转义/。您也不需要转义 < 或 >,因为它们对正则表达式引擎没有特殊意义。
"\<a.*?href=\"(.*?)\".*?>(.*?)</a>\si" @mickmackusa ?
preg_match_all("/(]>)(.?)()/", $contents, $impmatches, PREG_SET_ORDER);
经过测试,它会从任何 html 代码中获取所有标签。
【讨论】: