获取<a>链接标签。从Snoopy类中提取函数

作者:enenba | 发表于:2012-02-26 23:59 | 分类:php采集

这次分析过了Snoopy类,他里面有比较完善的匹配源码,我看到有function fetchlinks($URI)。也就是获取<a>中链接的函数,可以很简单的提取出来,此外我还发现,他的正则还支持高级语言中的三目运算,

<?php
function _striplinks($document) {
	preg_match_all("'<\s*a\s.*?href\s*=\s*([\"\'])?(?(1) (.*?)\\1 | ([^\s\>]+))'isx", $document, $links); 
	// catenate the non-empty matches from the conditional subpattern
	while (list($key, $val) = each($links[2])) {
		if (!empty($val))
			$match[] = $val;
	} while (list($key, $val) = each($links[3])) {
		if (!empty($val))
			$match[] = $val;
	} 
	// return the links
	return $match;
} 
$document = file_get_contents('http://www.qq.com');
$datalink = _striplinks($document);
printf("<p>输出link数据为:</p><pre>%s</pre>\n", var_export($datalink , true));
?>

我对源码去掉了注释。并上了个例子。很容易就得到了链接部分。

 

//分割线=====以下是对正则的解释分析,只想要功能的可以忽略以下内容==============//

 

 

正则分析:<\s*a\s.*?href\s*=\s*([\"\'])?(?(1) (.*?)\\1 | ([^\s\>]+))

'<\s*a\s.*?href\s*=\s*       # 查找 <a href=

([\"\'])?                    # 匹配单引或双引号为分组1,也可以没有

(?(1) (.*?)\\1 | ([^\s\>]+)) # 如果引号存在(分组1存在)匹配后引号

                             # 否则匹配非空格和非>内容

 

这个正则的难点也就是 (xxx)? (?(分组号) yyy|zzz)

我也是第一次碰到这样的正则,有点像高级语言的三目运算,我举个例子:

这个例子的目的是查找符合以下的规则

1、以123开头

2、后面有双引号则匹配引号和引号内的内容。

3、后面没有双引号,则是匹配后面为789的内容。

简单来说是匹配123"……" 或 123789

有引号优先匹配

<?php
$str = '123"456"789';
$search = '/123(")?(?(1).*?\\1|789)/';
preg_match($search,$str,$r);
echo $r[0];
//output 123"456"

echo '<br /><br />';

$str = '123456789';
$search = '/123(")?(?(1).*?\\1|789)/';
preg_match($search,$str,$r);
echo $r[0];
//output NULL

echo '<br /><br />';

$str = '123789456';
$search = '/123(")?(?(1).*?\\1|789)/';
preg_match($search,$str,$r);
echo $r[0];
//output 123789

?>

 

 看到了吧,

格式就像三目运算,高级语言是这样的:

(xxx)? yyy : zzz     如果xxx为真 执行yyy,否则执行zzzz

在正则中是:

(xxx)? (?(分组号) yyy|zzz) 如果xxx不为空 执行yyy,否则执行zzzz

 

就是这样~

end

上一篇: 正则高级技巧之三目运算   |   下一篇:emlog的伪静态还真简单» 标签: php源码 php函数 php采集 Snoopy

评论:

2012-03-08 12:42

模版而过。