如果要提取<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-regex-match-extracts-web-page-content-01

用浏览器的开发者工具分析,要提取绿色字体样式如下:

php-regex-match-extracts-web-page-content-02

 

代码实现:

<?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-regex-match-extracts-web-page-content-04