一直以来使用php解析html文档树都是一个难题。Simple HTML DOM parser 很好地解决了这个问题。可以通过这个php类来解析html文档,对其中的html元素进行操作 (PHP5+以上版本)。
解析器不仅仅只是帮助我们验证html文档;更能解析不符合W3C标准的html文档。它使用了类似jQuery的元素选择器,通过元素的id,class,tag等等来查找定位;同时还提供添加、删除、修改文档树的功能。和jq一样的操作还是很方便的。
有三种方式调用这个类:
从url中加载html文档
从字符串中加载html文档
从文件中加载html文档
03 | $html = new simple_html_dom(); |
09 | $html ->load( '<html><body>从字符串中加载html文档演示</body></html>' ); |
12 | $html ->load_file( 'path/file/test.html' ); |
查找html元素
可以使用find函数来查找html文档中的元素。返回的结果是一个包含了对象的数组。我们使用HTML DOM解析类中的函数来访问这些对象,下面给出几个示例
04 | $a = $html ->find( 'a' ); |
07 | $a = $html ->find( 'a' , 0); |
10 | $main = $html ->find( 'div[id=main]' ,0); |
13 | $divs = $html ->find( 'div[id]' ); |
16 | $divs = $html ->find( '[id]' ); |
03 | $ret = $html ->find( '#container' ); |
06 | $ret = $html ->find( '.foo' ); |
09 | $ret = $html ->find( 'a, img' ); |
12 | $ret = $html ->find( 'a[title], img[title]' ); |
元素属性操作
使用简单的正则表达式来操作属性选择器。
[attribute] – 选择包含某属性的html元素
[attribute=value] – 选择所有指定值属性的html元素
[attribute!=value]- 选择所有非指定值属性的html元素
[attribute^=value] -选择所有指定值开头属性的html元素
[attribute$=value] 选择所有指定值结尾属性的html元素
[attribute*=value] -选择所有包含指定值属性的html元素
如何避免解析器消耗过多内存
有时候可能Simple HTML DOM解析器消耗内存过多。如果php脚本占用内存太多,会导致网站停止响应等一系列严重的问题。解决的方法也很简单,在解析器加载html文档并使用完成后,记得清理掉这个对象就可以了。
下面看看微博热词抓取的源码示例
03 | header( 'Content-Type:text/html;charset=gbk' ); |
04 | include "simple_html_dom.php" ; |
10 | function __construct( $cluster ) { |
11 | $this ->memcache = new Memcache; |
12 | foreach ( $cluster [ 'memcached' ] as $server ) { |
13 | $this ->memcache->addServer( $server [ 'host' ], $server [ 'port' ]); |
17 | function fetch( $cache_key ) { |
18 | return $this ->memcache->get( $cache_key ); |
21 | function store( $cache_key , $val , $expire = 7200) { |
22 | $this ->memcache->set( $cache_key , $val , MEMCACHE_COMPRESSED, $expire ); |
26 | $this ->memcache-> flush (); |
29 | function delete ( $cache_key , $timeout = 0) { |
30 | $this ->memcache-> delete ( $cache_key , $timeout ); |
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); |
44 | function curl_fetch( $url , $time = 3) { |
46 | curl_setopt( $ch , CURLOPT_URL, $url ); |
47 | curl_setopt( $ch , CURLOPT_TIMEOUT, $time ); |
48 | curl_setopt( $ch , CURLOPT_RETURNTRANSFER, 1); |
50 | $data = curl_exec( $ch ); |
51 | $errno = curl_errno( $ch ); |
54 | $err = "[CURL] url:{$url} ; errno:{$errno} ; info:" . curl_error( $ch ) . ";" ; |
63 | $cluster [ "memcached" ] = array ( |
64 | array ( "host" => "10.11.1.1" , "port" => 11211), |
68 | $cache_key = md5( "weibo" . $url ); |
75 | $content = curl_fetch( $url ); |
76 | if ( $content === false) |
79 | $html = str_get_html( $content ); |
80 | $a = $html ->find( 'script' , 8); |
82 | $a = str_replace ( array ( '\\"' , '\\/' , "\\n ", " \\t "), array('" ', '/' , "" , "" ), $a ); |
83 | $pos = strpos ( $a , '<div class="hot_ranklist">' ); |
84 | $a = substr ( $a , $pos ); |
89 | $html = str_get_html( $a ); |
91 | foreach ( $html ->find( 'table[id=event]' , 0)->find( '.rank_content' ) as $element ) { |
92 | $arr [] = unicode_hex_2_gbk( $element ->find( "a" , 0)->plaintext); |
95 | $str = implode( "," , $arr ); |