PHP 正则匹配提取网页内容
如果要提取<div class="xxx" id="yyy">之间的网页内容,用 preg_match不用preg_match_all
如果要提取<div>里面的所有的 <li></li>标签中的内容,可以用preg_match_all
示例:提取IP地址的地理位置
需求分析:
浏览器打开: http://www.ip138.com/ips138.asp?ip=218.30.180.177
需提取结果:提取下图中的绿色字体部分
用浏览器的开发者工具分析,要提取绿色字体样式如下:
代码实现:
<?php
function check_ip_ip138($ip='218.30.180.177') {
$url = 'http://www.ip138.com/ips138.asp?ip=' . $ip;
echo "<br><br> url : " . $url;
$ch = curl_init();
$header = array();
array_push($header, 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36');
array_push($header, 'Referer:' . $url);
array_push($header, 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');
array_push($header, 'upgrade-insecure-requests:1');
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1); //0表示不输出Header,1表示输出
curl_setopt($ch, CURLOPT_NOBODY, 0); //0表示不输出Body,1表示输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
// $output = file_get_contents($url); // also is ok
$output = mb_convert_encoding($output, "utf-8", "gbk");
// 提取 <ul>
$pattern = '/<ul class="ul1">(.+?)<\/ul>/is';
preg_match($pattern, $output, $match);
echo "<br><br>match: <br>";
var_dump($match);
echo "<br><br>match[1]: <br>";
var_dump($match[1]);
// 提取 <li>
$pattern_2 = '/<li>(.+?)<\/li>/is';
preg_match_all($pattern_2, $match[1], $match_2);
echo "<br><br>match_2: <br>";
var_dump($match_2);
echo "<br><br>match_2[1]: <br>";
var_dump($match_2[1]);
$match_2_values = "";
foreach ($match_2[1] as $key => $value) {
// 提取绿色字体冒号(:)后的字体
$match_2_values = $match_2_values . explode(":", $value)[1] . "|";
}
// 去掉末尾多余的一个"|"
$match_2_values = substr($match_2_values, 0, -1);
echo "<br><br>match_2_values: " . $match_2_values;
}
check_ip_ip138();
?>
运行结果:
url : http://www.ip138.com/ips138.asp?ip=218.30.180.177
match:
array (size=2)
0 => string '<ul class="ul1"><li>本站数据:北京市北京市 电信</li><li>参考数据1:北京北京 电信</li><li>参考数据2:中国 电信</li></ul>' (length=154)
1 => string '<li>本站数据:北京市北京市 电信</li><li>参考数据1:北京北京 电信</li><li>参考数据2:中国 电信</li>' (length=133)
match[1]:
<li>本站数据:北京市北京市 电信</li><li>参考数据1:北京北京 电信</li><li>参考数据2:中国 电信</li>' (length=133)
match_2:
array (size=2)
0 =>
array (size=3)
0 => string '<li>本站数据:北京市北京市 电信</li>' (length=50)
1 => string '<li>参考数据1:北京北京 电信</li>' (length=45)
2 => string '<li>参考数据2:中国 电信</li>' (length=38)
1 =>
array (size=3)
0 => string '本站数据:北京市北京市 电信' (length=41)
1 => string '参考数据1:北京北京 电信' (length=36)
2 => string '参考数据2:中国 电信' (length=29)
match_2[1]:
array (size=3)
0 => string '本站数据:北京市北京市 电信' (length=41)
1 => string '参考数据1:北京北京 电信' (length=36)
2 => string '参考数据2:中国 电信' (length=29)
match_2_values: 北京市北京市 电信|北京北京 电信|中国 电信
上图可见,提取的绿色字体如下:
match_2_values: 北京市北京市 电信|北京北京 电信|中国 电信
正确提取绿色字体成功!
总结:
上述示例中,既用到了preg_match,也用到了preg_match_all,区别是:
preg_match,用于提取单个特定元素,例如:<ul class="ul1">,<div id="yyy">等
preg_match_all,用于提取多个类似元素,例如:<li>,<td>等
并且,preg_match 和 preg_match_all 提取出的数组元素,第一个元素(下标为0)是完全匹配(包含<ul>或<li>),第二个(下标为1)才是里面内容匹配,细心的可能发现了,代码实现里,用的都是第二个元素(下标为1),例如:$match[1] 和 $match_2[1],感兴趣的可以自己用浏览器开发者工具进行调试。
下面给出我调试时的分析结果:
参考推荐:
PHP 获取网页标题(title)、描述(description)、关键字(keywords)等meta信息
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2019-01-03 19:35:59
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!
转载注明: PHP 正则匹配提取网页内容 (米扑博客)


