一直以来使用php解析html文档树都是一个难题。Simple HTML DOM parser 很好地解决了这个问题。可以通过这个php类来解析html文档,对其中的html元素进行操作 (PHP5+以上版本)。
解析器不仅仅只是帮助我们验证html文档;更能解析不符合W3C标准的html文档。它使用了类似jQuery的元素选择器,通过元素的id,class,tag等等来查找定位;同时还提供添加、删除、修改文档树的功能。和jq一样的操作还是很方便的。
有三种方式调用这个类:
从url中加载html文档
从字符串中加载html文档
从文件中加载html文档
01 |
<?php |
02 |
//
新建一个Dom实例 |
03 |
$html = new simple_html_dom(); |
04 |
05 |
//
从url中加载 |
06 |
$html ->load_file( ‘http://www.xxx.com‘ ); |
07 |
08 |
//
从字符串中加载 |
09 |
$html ->load( ‘<html><body>从字符串中加载html文档演示</body></html>‘ ); |
10 |
11 |
//从文件中加载 |
12 |
$html ->load_file( ‘path/file/test.html‘ ); |
13 |
?> |
查找html元素
可以使用find函数来查找html文档中的元素。返回的结果是一个包含了对象的数组。我们使用HTML DOM解析类中的函数来访问这些对象,下面给出几个示例
01 |
<?php |
02 |
03 |
//查找html文档中的超链接元素 |
04 |
$a = $html ->find( ‘a‘ ); |
05 |
06 |
//查找文档中第(N)个超链接,如果没有找到则返回空数组. |
07 |
$a = $html ->find( ‘a‘ ,
0); |
08 |
09 |
//
查找id为main的div元素 |
10 |
$main = $html ->find( ‘div[id=main]‘ ,0); |
11 |
12 |
//
查找所有包含有id属性的div元素 |
13 |
$divs = $html ->find( ‘div[id]‘ ); |
14 |
15 |
//
查找所有包含有id属性的元素 |
16 |
$divs = $html ->find( ‘[id]‘ ); |
17 |
?> |
01 |
<?php |
02 |
//
查找id=‘#container‘的元素 |
03 |
$ret = $html ->find( ‘#container‘ ); |
04 |
05 |
//
找到所有class=foo的元素 |
06 |
$ret = $html ->find( ‘.foo‘ ); |
07 |
08 |
//
查找多个html标签 |
09 |
$ret = $html ->find( ‘a,
img‘ ); |
10 |
11 |
//
还可以这样用 |
12 |
$ret = $html ->find( ‘a[title],
img[title]‘ ); |
13 |
?> |
01 |
<?php |
02 |
//
返回父元素 |
03 |
$e ->parent; |
04 |
05 |
//
返回子元素数组 |
06 |
$e ->children; |
07 |
08 |
//
通过索引号返回指定子元素 |
09 |
$e ->children(0); |
10 |
11 |
//
返回第一个资源速 |
12 |
$e ->first_child
(); |
13 |
14 |
//
返回最后一个子元素 |
15 |
$e ->last
_child (); |
16 |
17 |
//
返回上一个相邻元素 |
18 |
$e ->prev_sibling
(); |
19 |
20 |
//返回下一个相邻元素 |
21 |
$e ->next_sibling
(); |
22 |
?> |
元素属性操作
使用简单的正则表达式来操作属性选择器。
[attribute] – 选择包含某属性的html元素
[attribute=value] – 选择所有指定值属性的html元素
[attribute!=value]- 选择所有非指定值属性的html元素
[attribute^=value] -选择所有指定值开头属性的html元素
[attribute$=value] 选择所有指定值结尾属性的html元素
[attribute*=value] -选择所有包含指定值属性的html元素
如何避免解析器消耗过多内存
有时候可能Simple HTML DOM解析器消耗内存过多。如果php脚本占用内存太多,会导致网站停止响应等一系列严重的问题。解决的方法也很简单,在解析器加载html文档并使用完成后,记得清理掉这个对象就可以了。
1 |
<?php |
2 |
$html ->clear(); |
3 |
?> |
下面看看微博热词抓取的源码示例
01 |
<?php |
02 |
03 |
header( ‘Content-Type:text/html;charset=gbk‘ ); |
04 |
include "simple_html_dom.php" ; |
05 |
06 |
class Tmemcache
{ |
07 |
08 |
protected $memcache ; |
09 |
10 |
function __construct( $cluster )
{ |
11 |
$this ->memcache
= new Memcache; |
12 |
foreach ( $cluster [ ‘memcached‘ ] as $server )
{ |
13 |
$this ->memcache->addServer( $server [ ‘host‘ ], $server [ ‘port‘ ]); |
14 |
} |
15 |
} |
16 |
17 |
function fetch( $cache_key )
{ |
18 |
return $this ->memcache->get( $cache_key ); |
19 |
} |
20 |
21 |
function store( $cache_key , $val , $expire =
7200) { |
22 |
$this ->memcache->set( $cache_key , $val ,
MEMCACHE_COMPRESSED, $expire ); |
23 |
} |
24 |
25 |
function flush ()
{ |
26 |
$this ->memcache-> flush (); |
27 |
} |
28 |
29 |
function delete ( $cache_key , $timeout =
0) { |
30 |
$this ->memcache-> delete ( $cache_key , $timeout ); |
31 |
} |
32 |
33 |
} |
34 |
35 |
function unicode_hex_2_gbk( $name )
{ |
36 |
$a =
json_decode( ‘{"a":"‘ . $name . ‘"}‘ ); |
37 |
if (isset( $a )
&& is_object ( $a ))
{ |
38 |
return iconv( ‘UTF-8‘ , ‘GBK//IGNORE‘ , $a ->a); |
39 |
return $a ->a; |
40 |
} |
41 |
return null; |
42 |
} |
43 |
44 |
function curl_fetch( $url , $time =
3) { |
45 |
$ch =
curl_init(); |
46 |
curl_setopt( $ch ,
CURLOPT_URL, $url ); |
47 |
curl_setopt( $ch ,
CURLOPT_TIMEOUT, $time ); |
48 |
curl_setopt( $ch ,
CURLOPT_RETURNTRANSFER, 1); |
49 |
50 |
$data =
curl_exec( $ch ); |
51 |
$errno =
curl_errno( $ch ); |
52 |
53 |
if ( $errno >
0) { |
54 |
$err = "[CURL]
url:{$url} ; errno:{$errno} ; info:" .
curl_error( $ch )
. ";" ; |
55 |
echo $err ; |
56 |
$data =
false; |
57 |
} |
58 |
59 |
curl_close( $ch ); |
60 |
return $data ; |
61 |
} |
62 |
63 |
$cluster [ "memcached" ]
= array ( |
64 |
array ( "host" => "10.11.1.1" , "port" =>
11211), |
65 |
); |
66 |
//$memcache
= new Tmemcache($cluster); |
67 |
$url = "http://s.weibo.com/top/summary?cate=total&key=event" ; |
68 |
$cache_key =
md5( "weibo" . $url ); |
69 |
//$str
= $memcache->fetch($cache_key); |
70 |
//if
(!isset($_GET["nocache"]) && !empty($str)) { |
71 |
//
echo $str; |
72 |
//
exit; |
73 |
//} |
74 |
75 |
$content =
curl_fetch( $url ); |
76 |
if ( $content ===
false) |
77 |
exit ; |
78 |
79 |
$html =
str_get_html( $content ); |
80 |
$a = $html ->find( ‘script‘ ,
8); |
81 |
//测试 |
82 |
$a = str_replace ( array ( ‘\\"‘ , ‘\\/‘ ,
"\\n ",
" \\t "),
array(‘" ‘, ‘/‘ , "" , "" ), $a ); |
83 |
$pos = strpos ( $a , ‘<div
class="hot_ranklist">‘ ); |
84 |
$a = substr ( $a , $pos ); |
85 |
//////// |
86 |
//echo
"<xmp>"; |
87 |
//echo
($a); |
88 |
//echo
"</xmp>"; |
89 |
$html =
str_get_html( $a ); |
90 |
$arr = array (); |
91 |
foreach ( $html ->find( ‘table[id=event]‘ ,
0)->find( ‘.rank_content‘ ) as $element )
{ |
92 |
$arr []
= unicode_hex_2_gbk( $element ->find( "a" ,
0)->plaintext); |
93 |
} |
94 |
$html ->clear(); |
95 |
$str =
implode( "," , $arr ); |
96 |
//if
(!isset($_GET["nocache"])) |
97 |
//
$memcache->store($cache_key, $str, 3600); |
98 |
echo $str ; |