今天博客因为需要把文章所有外部链接替换成一个跳转页面的链接,因此要找出文章里所有a标签网址,然后进行替换。
看到网上有不少实现代码,但看了后发现都不够严密,因为这些代码都没有考虑到各种不标准的写法,如有的网址有单引号引住,有的是双引号引住,而有的连单双引号都没有,还有空格问题等等。
为此,我研究了一下正则表达式语法,自己写了一个“万能”正则表达式,能匹配到a标签里各种写法的网址,可谓是完全无视html语法了。
【实例】
html代码如:
<ul class="partner"> <li><a href='http://www.vps5u.com/?ref=2170-2-5' target =_blank title='vps5u-1' >vps评测网-1</a></li> <li><a href = 'http://www.vps5u.com/' target =_blank title='vps5u-2' >vps评测网-2</a></li> <li><a href ="http://vps5u.com/" target =_blank title="vps5u-3" >vps评测网-3</a></li> <li><a href=https://www.vps5u.com/ target =_blank title=vps5u-4 >vps评测网-4</a></li> <li><a href= http://www.vps5u.com/vps/index.html target =_blank title= vps5u-5 >vps评测网-5</a></li> </ul>
注意上面的各个网址写法,都不一样,各种不标准不严密的写法都有,我们写代码要做到能忽视这些问题。
我们现在要找出所有a标签的网址,我写的“万能”正则表达式如下:
$pattern = '/<a(?:[\s\S]*?)href\s*?=\s*[\'"]?(http(?:s?):\/\/([^\/]+)?([^\s\'"]+)?)[?:\s\'"]?[^>]*>([\s\S]*?)<\/a>/i'; preg_match_all($pattern, $data, $links); // $data 为上面的html代码字符串 $links 是一个存放匹配结果的多维数组 echo var_dump($links); //输出数组看匹配结果
输出的数组是这样:
array(5) { [0]=> array(5) { [0]=> string(95) "<a href='http://www.vps5u.com/?ref=2170-2-5' target =_blank title='vps5u-1' >vps评测网-1</a>" [1]=> string(84) "<a href = 'http://www.vps5u.com/' target =_blank title='vps5u-2' >vps评测网-2</a>" [2]=> string(79) "<a href ="http://vps5u.com/" target =_blank title="vps5u-3" >vps评测网-3</a>" [3]=> string(79) "<a href=https://www.vps5u.com/ target =_blank title=vps5u-4 >vps评测网-4</a>" [4]=> string(96) "<a href= http://www.vps5u.com/vps/index.html target =_blank title= vps5u-5 >vps评测网-5</a>" } [1]=> array(5) { [0]=> string(34) "http://www.vps5u.com/?ref=2170-2-5" [1]=> string(21) "http://www.vps5u.com/" [2]=> string(17) "http://vps5u.com/" [3]=> string(22) "https://www.vps5u.com/" [4]=> string(35) "http://www.vps5u.com/vps/index.html" } [2]=> array(5) { [0]=> string(13) "www.vps5u.com" [1]=> string(13) "www.vps5u.com" [2]=> string(9) "vps5u.com" [3]=> string(13) "www.vps5u.com" [4]=> string(13) "www.vps5u.com" } [3]=> array(5) { [0]=> string(14) "/?ref=2170-2-5" [1]=> string(1) "/" [2]=> string(1) "/" [3]=> string(1) "/" [4]=> string(15) "/vps/index.html" } [4]=> array(5) { [0]=> string(14) "vps评测网-1" [1]=> string(14) "vps评测网-2" [2]=> string(14) "vps评测网-3" [3]=> string(14) "vps评测网-4" [4]=> string(14) "vps评测网-5" } }
从数组可清晰看到:
$links[0]是所有<a>标签。 $links[1]是所有href。 $links[2]是所有域名,如:www.vps5u.com。 $links[4]是所有a标签内容。
现在,我们就可以用php代码从这个数组里取出我们想要的东西了。例如要取出所有网址,就读取$links[1]里所有数值,用for
循环即可,代码如下:
for ($x = 0; $x < count($links[1]); $x++) { // count()函数是获得数组长度 echo $links[1][$x]."-----"; }
用同样的方法,可获得其他内容,如所有a标签内容,所有域名。
本文运用的正则表达式语法解释:
- \s
空白字符 - \S
非空白字符 - /fo+/
正则表达式中包含“+”元字符,表示可以与目标对象中的 “fool”, “fo”, 或者 “football”等在字母f后面连续出现一个或多个字母o的字符串相匹配。 - /eg*/
正则表达式中包含“*”元字符,表示可以与目标对象中的 “easy”, “ego”, 或者 “egg”等在字母e后面连续出现零个或多个字母g的字符串相匹配。 - /Wil?/
正则表达式中包含“?”元字符,表示可以与目标对象中的 “Win”, 或者“Wilson”,等在字母i后面连续出现零个或一个字母l的字符串相匹配。