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