其实从PHP5开始,PHP就为咱们提供了一个弱小的解析和生成XML相干操作的类,也就是咱们明天要讲的 DOMDocument 类。不过我预计大部分人在爬取网页时还是会喜爱用正则去解析网页内容,学了明天的这个类下回就能够尝试下应用这个PHP自带的形式来进行解析剖析了。

解析HTML

// 解析 HTML$baidu = file_get_contents('https://www.baidu.com');$doc = new DOMDocument();@$doc->loadHTML($baidu);// 百度输入框$inputSearch = $doc->getElementById('kw');var_dump($inputSearch);// object(DOMElement)#2 //     ....echo $inputSearch->getAttribute('name'), PHP_EOL; // wd// 获取所有图片的链接$allImageLinks = [];$imgs = $doc->getElementsByTagName('img');foreach($imgs as $img){    $allImageLinks[] = $img->getAttribute('src');}print_r($allImageLinks);// Array// (//     [0] => //www.baidu.com/img/baidu_jgylogo3.gif//     [1] => //www.baidu.com/img/bd_logo.png//     [2] => http://s1.bdstatic.com/r/www/cache/static/global/img/gs_237f015b.gif// )// 利用 parse_url 剖析链接foreach($allImageLinks as $link){    print_r(parse_url($link));}// Array// (//     [host] => www.baidu.com//     [path] => /img/baidu_jgylogo3.gif// )// Array// (//     [host] => www.baidu.com//     [path] => /img/bd_logo.png// )// Array// (//     [scheme] => http//     [host] => s1.bdstatic.com//     [path] => /r/www/cache/static/global/img/gs_237f015b.gif// )

是不是感觉好清晰,好有面向对象的感觉。就像第一次应用 ORM库 来进行数据库操作一样的感觉。咱们一段一段来看。

$baidu = file_get_contents('https://www.baidu.com');$doc = new DOMDocument();@$doc->loadHTML($baidu);

首先是加载文档内容,这个比拟好了解,间接应用 loadHTML() 办法加载 HTML 内容。它还提供了其它的几个办法,别离是:load() 从一个文件加载XML;loadXML() 从字符串加载XML;loadHTMLFile() 从文件加载HTML。

// 百度输入框$inputSearch = $doc->getElementById('kw');var_dump($inputSearch);// object(DOMElement)#2 //     ....echo $inputSearch->getAttribute('name'), PHP_EOL; // wd

接下来咱们应用和前端 JS 一样的 DOM 操作API来操作HTML外面的元素。这个例子中就是获取百度的文本框,间接应用 getElementById() 办法取得id为指定内容的 DOMElement 对象。而后就能够获取它的值、属性之类的内容了。

// 获取所有图片的链接$allImageLinks = [];$imgs = $doc->getElementsByTagName('img');foreach($imgs as $img){    $allImageLinks[] = $img->getAttribute('src');}print_r($allImageLinks);// Array// (//     [0] => //www.baidu.com/img/baidu_jgylogo3.gif//     [1] => //www.baidu.com/img/bd_logo.png//     [2] => http://s1.bdstatic.com/r/www/cache/static/global/img/gs_237f015b.gif// )// 利用 parse_url 剖析链接foreach($allImageLinks as $link){    print_r(parse_url($link));}// Array// (//     [host] => www.baidu.com//     [path] => /img/baidu_jgylogo3.gif// )// Array// (//     [host] => www.baidu.com//     [path] => /img/bd_logo.png// )// Array// (//     [scheme] => http//     [host] => s1.bdstatic.com//     [path] => /r/www/cache/static/global/img/gs_237f015b.gif// )

这一段例子则是获取HTML文档中所有的图片链接。相比正则来说,是不是不便很多,而且代码自身就是自解释的,不必思考正则的匹配生效的问题。配合另外一个PHP中自带的 parse_url() 办法也能十分不便地对链接进行剖析,提取本人想要的内容。

XML的解析和对HTML的解析也是相似的,都应用 DOMDocument 和 DOMElement 提供的这个办法接口就能够很不便的进行解析了。那么咱们想要生成一个规范格局的XML呢?当然也十分的简略,不须要再去拼接字符串了,应用这个类一样的进行对象化的操作。

生成一个XML

// 生成一个XML文档$xml = new DOMDocument('1.0', 'UTF-8');$node1 = $xml->createElement('First', 'This is First Node.');$node1->setAttribute('type', '1');$node2 = $xml->createElement('Second');$node2->setAttribute('type', '2');$node2_child = $xml->createElement('Second-Child', 'This is Second Node Child.');$node2->appendChild($node2_child);$xml->appendChild($node1);$xml->appendChild($node2);print $xml->saveXML();/*<?xml version="1.0" encoding="UTF-8"?><First type="1">This is First Node.</First><Second type="2"><Second-Child>This is Second Node Child.</Second-Child></Second>*/

其实只有有一点点的前端 JS 的根底都不难看出这段代码的含意。应用 createElement() 办法发明 DOMElement 对象,而后就能够为它增加属性和内容。应用 appendChild() 办法就能够为以后的 DOMElement 或者 DOMDocument 增加上级节点。最初应用 saveXML() 就可能生成规范的XML格局内容了。

总结

通过下面两个简略的小例子,置信大家曾经对这个 DOMDocument 操作XML类文件解析的形式十分感兴趣了。不过绝对于正则解析的形式它们的性能有多大的差别并没有找到相干的测试,不过个别失常的状况下网站的HMTL文档都不会太大,毕竟各个网站也会思考本身的加载速度,如果文档十分大的话用户体验也会很差,所以这套接口用来进行日常爬虫的剖析解决工作根本是没有任何问题的。

测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202002/source/PHP%E4%B8%AD%E4%BD%BF%E7%94%A8DOMDocument%E6%9D%A5%E5%A4%84%E7%90%86HTML%E3%80%81XML%E6%96%87%E6%A1%A3.php

参考文档:
https://www.php.net/manual/zh/class.domdocument.php

===========

各自媒体平台均可搜寻【硬核项目经理】