尝试将DOMDocument :: loadHTMLFile与生成的url一起使用

时间:2014-11-23 07:34:59

标签: php domdocument

我使用我构建的url调用DOMDocument :: loadHTMLFile方法。

这是我用来构建网址的代码:

$url = "http://en.wikipedia.org".$path

$path是从另一个文件的href属性获得的。当我回应它时返回/wiki/Pop_music

如果我将网址硬编码为http://en.wikipedia.org/wiki/Pop_music页面返回正常,但如果我尝试使用生成的路径,则会收到错误。

这是我目前正在使用的代码:

    foreach ($paths as $path) 
    {
        echo $path;                                         // will cause error 
        //echo $path = '/wiki/Pop_music';                       // will work
        $url = "http://en.wikipedia.org"."$path";
        $doc = getHTML($url, 1);

        if($doc !== false)
        {
            $xpath = new DOMXPath($doc);
            $xpathCode = "//h1[@id='firstHeading']";
            $nodes = $xpath->query($xpathCode);
            echo $nodes->item(0)->nodeValue."<br />";
        }
    }

getHTML功能是:

function getHTML($url, $domainID)
{
    $conArtistsCrawler = new mysqli(HOST, USERNAME, PASSWORD, CRAWLER_DB_NAME);

    // Load HTML
    $doc = new DOMDocument();
    $isSuccessful = $doc->loadHTMLFile($url);

    // Update the time to show that the domain was crawled.
    $sql = "UPDATE Domain SET LastCrawled = CURRENT_TIMESTAMP() WHERE DomainID = '$domainID'";
    $conArtistsCrawler->query($sql);
    $conArtistsCrawler->close();

    // Delay 1 second after the request to avoid getting BANNED
    sleep(1);

    // Check to see if URL is valid
    if($isSuccessful === false)
    {
        //URL invalid!
        echo "\"".$url."\" is invalid<br>";
        return false;
    }

    return $doc;
}

代码输出:

使用硬编码路径:

  

警告:DOMDocument :: loadHTMLFile():ID protected-icon已经存在   在http://en.wikipedia.org/wiki/Dido%20(singer)中定义,行:60英寸   第77行/Applications/MAMP/htdocs/Assignments/Assignment4/test.php   / wiki / Pop_music警告:DOMDocument :: loadHTMLFile():标记音频   在http://en.wikipedia.org/wiki/Pop_music中无效,行:225英寸   第77行/Applications/MAMP/htdocs/Assignments/Assignment4/test.php

     

警告:DOMDocument :: loadHTMLFile():标记源无效   http://en.wikipedia.org/wiki/Pop_music,行:225英寸   第77行/Applications/MAMP/htdocs/Assignments/Assignment4/test.php   流行音乐

使用路径变量:

  

警告:DOMDocument :: loadHTMLFile():已在中定义的ID protected-icon   http://en.wikipedia.org/wiki/Dido%20(singer),行:60英寸   第77行/Applications/MAMP/htdocs/Assignments/Assignment4/test.php   /维基/ Pop_music

     

警告:   DOM文档:: loadHTMLFile(http://en.wikipedia.org/wiki/Pop_music%3Cbr%20/%3E):   无法打开流:HTTP请求失败! HTTP / 1.1 400错误请求   在/Applications/MAMP/htdocs/Assignments/Assignment4/test.php上   77

     

警告:DOMDocument :: loadHTMLFile():I / O警告:加载失败   外部实体“http://en.wikipedia.org/wiki/Pop_music%3Cbr%20/%3E”   在/Applications/MAMP/htdocs/Assignments/Assignment4/test.php上   77“http://en.wikipedia.org/wiki/Pop_music”无效

1 个答案:

答案 0 :(得分:3)

简答:

嗯,你得到的错误是由于$doc不是DOMDocument对象,但它是布尔值false。由于您正在禁止DOMDocument警告,因此您无法知道getHTML()返回false的原因。

  

所以,丢失@运算符,检查DOMDocument抱怨的内容   并从那里进行调试。

修改

  

但是我仍然不确定为什么当我传入变量时我会得到一个   当我硬编码时,不同的结果。当我回显两个路径值   或网址值看起来相同

他们当然不一样。 Pop_Music之后有一个<br/>标记,它使网址无效。

长答案

运行此脚本:

$path = '/wiki/Pop_music';
$url = "http://en.wikipedia.org$path";
$doc = new \DOMDocument();
$success = @$doc->loadHTMLFile($url);

if ($success) {
    $xpath = new DOMXPath($doc);
    $xpathCode = "//h1[@id='firstHeading']";
    $nodes = $xpath->query($xpathCode);
    echo $nodes->item(0)->nodeValue."<br />";
}

产生以下结果:

Pop music<br />

因此,为了解决您的脚本问题,您应该做一些事情......

丢失@运算符

请勿使用@运算符。这会吃掉任何警告,并使调试变得更加困难。事实上,DOMDocument抱怨很多,有时候错误不是真正的错误(比如一些HTML5标签)。但它也会抛出有效的警告,例如格式错误的HTML或无法访问的URL。

  

处理此问题的最佳方法是使用 custom error handler 并加载它   在DOMDocument之前。

这将使您能够消化DOMDocument给出的警告,并区分重要和琐碎的警告。

示例:

set_error_handler(function($errno, $errstr, $errfile, $errline) {
    //Digest error here
});

$doc = new DOMDocument();
$isSuccessful = $doc->loadHTMLFile($url);

restore_error_handler();

注意:您也可以使用 libxml_use_internal_errors(true);

您的getHTML函数返回不一致的类型

您的getHTML函数可以返回 DOMDocument对象布尔值。虽然这不是一件坏事本身(在内部,PHP用很多函数来做),这意味着你不能认为$doc是一个对象,因为它可以是布尔值为false。因此,在将其作为参数传递给XDOMPath之前,必须先测试返回的值。事实上,这就是你得到的错误:

  

您将布尔值传递给XDOMPath而不是DOMDocument对象   到XDOMPath

在函数中抛出异常(或错误)或在传递给XDOMPath之前测试返回的值。

示例:

$doc = getHTML($url, 1);
if ($doc instanceof \DOMDocument) {
    $xpath = new DOMXPath($doc);
}