从Snoopy类中提取函数:获取链接标签

2013年10月9日 发表评论 阅读评论

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

<?php
function _striplinks($document) {
	preg_match_all("'<s*as.*?hrefs*=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*as.*?hrefs*=s*(["'])?(?(1) (.*?)\1 | ([^s>]+))

'<s*as.*?hrefs*=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




本站的发展离不开您的资助,金额随意,欢迎来赏!

You can donate through PayPal.
My paypal id: itybku@139.com
Paypal page: https://www.paypal.me/361way

分类: perl/php/python/gawk/sed 标签:
  1. 本文目前尚无任何评论.
  1. 2013年10月9日15:48 | #1