PHP类库DomDocument类
in php with 0 comment

PHP类库DomDocument类

in php with 0 comment

最近帮朋友采集点数据,因为之前也采集过小说、bt链接这种。所以感觉问题不大,上手就写。

之前用的最多的大多是SimpleHtmlDom或者phpQuery之类的老工具了(工具虽老但用着顺手啊哈哈)

这次为了上手快用的TP5.1在跑,但是如何引用SimpleHtmlDom就有些麻烦了。因为TP5.1的自动加载机制是根据命名空间和文件命名来加载的,但是SimpleHtmlDom这个单文件中封装了2个类就有些麻烦了。

其实如果只是获取页面内容,靠curl和file_get_contents也能拿到链接。只是DOM树解析这块有些棘手。

那么问题来了,PHP有自带的DOM解析库么?

没错,我在PHP手册中找到了内置的DOM操作库。传送门

因为我用的XPath抓取的,所以也引用了DOMXPATH类。

这里放一下自己封的两个函数。

    /**
     * 获取一个DOMXPath实例
     * @param string $htmlCode 页面源码
     */
    function getDomXPath($htmlCode){
        // 阻止因为页面元素不规范引起的报错
        $libxml_previous_state = libxml_use_internal_errors(true);

        $dom = new \DOMDocument();
        $dom->loadHTML($htmlCode);

        // 阻止因为页面元素不规范引起的报错
        libxml_clear_errors();
        libxml_use_internal_errors($libxml_previous_state);

        $xpath = new \DOMXPath($dom);

        return $xpath;
    }

    /**
     * 使用xpath表达式获取值 默认返回对象
     * @param \DOMXPath $xpath      xpath实例
     * @param string    $xPathExp   xpath表达式
     * @param bool      $all        是否匹配多个对象
     * @return object|null
     */
    function getValueByXPath(\DOMXPath &$xpath,$xPathExp,$all = false){
        $node = $xpath->query($xPathExp);
        if($node->length > 0){
            if($all){
                $nodeValue = [];
                foreach ($node as $childNode){
                    $nodeValue[] = $childNode;
                }
                return $nodeValue;
            }else{
                return $node[0];
            }
        }else{
            throw new Exception($xPathExp.' 未匹配到内容!');
        }
    }

    //demo
    $item = [];
    $xPath = $this->getDomXPath($htmlCode);
    $item['title'] = $this->getValueByXPath($xpath,'/html/body/div[9]/h1')->nodeValue;
    ...

因为有些html的代码格式(or xml格式)不标准,会导致DOMDocument的loadHTML()方法报错,解决方法是在开头和结尾加上这三行屏蔽错误的代码。参考:PHP: 禁止 DomDocument::loadHTML() 对不规范的HTML输出警告信息

// 阻止因为页面元素不规范引起的报错
$libxml_previous_state = libxml_use_internal_errors(true);

code...

// 阻止因为页面元素不规范引起的报错
libxml_clear_errors();
libxml_use_internal_errors($libxml_previous_state);
Comments are closed.