一直以来使用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 ;
|