我使用我构建的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”无效
答案 0 :(得分:3)
嗯,你得到的错误是由于$doc
不是DOMDocument对象,但它是布尔值false。由于您正在禁止DOMDocument警告,因此您无法知道getHTML()
返回false的原因。
所以,丢失@运算符,检查DOMDocument抱怨的内容 并从那里进行调试。
修改强>
但是我仍然不确定为什么当我传入变量时我会得到一个 当我硬编码时,不同的结果。当我回显两个路径值 或网址值看起来相同
<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函数可以返回 DOMDocument对象或布尔值。虽然这不是一件坏事本身(在内部,PHP用很多函数来做),这意味着你不能认为$doc
是一个对象,因为它可以是布尔值为false。因此,在将其作为参数传递给XDOMPath之前,必须先测试返回的值。事实上,这就是你得到的错误:
您将布尔值传递给XDOMPath而不是DOMDocument对象 到XDOMPath
在函数中抛出异常(或错误)或在传递给XDOMPath之前测试返回的值。
示例:强>
$doc = getHTML($url, 1);
if ($doc instanceof \DOMDocument) {
$xpath = new DOMXPath($doc);
}