通分析过了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
《从Snoopy类中提取函数:获取链接标签》有1条评论