【发布时间】:2016-07-29 23:05:12
【问题描述】:
我正在尝试创建一个小型 URL 爬虫,供我工作的公司内部使用。
目前,我有一个帮助程序类,所有的魔法都会发生,还有一个 index.php 可以显示结果。
我想要做的是,给出一个 URL 和代码来获取网站包含的所有页面 URL,以便在屏幕上显示。
但是,等待这个 foreach 循环完成需要一段时间,因此,我想在循环的每次迭代之后回显链接。
我无法让它工作。我不知道是链接获取代码,还是我尝试刷新输出缓冲区。我在这里遵循了这个问题中的例子:Echo 'string' while every long loop iteration (flush() not working)
我的代码在下面(没有刷新尝试)
// INDEX.PHP
require_once('helper.php');
$helper = new Helper();
flush();
ob_flush();
$found = $helper->crawlSite('http://www.bbc.co.uk', 'http://www.bbc.uk');
echo count($found);
// HELPER.PHP
class Helper
{
private $checked = [];
private $foundUrls = [];
public function __construct()
{
}
public function getHTML($url)
{
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$html = curl_exec($curl);
curl_close($curl);
return $html;
}
public function getTagFromHTML($html, $tag)
{
$dom = new DOMDocument();
$dom->loadHTML($html);
return $dom->getElementsByTagName($tag);
}
function crawlSite($url, $initialUrl)
{
$html = $this->getHTML($url);
$links = $this->getTagFromHTML($html, 'a');
foreach ($links as $link) {
echo $link->getAttribute('href') . '<br>';
flush();
ob_flush();
if (!in_array($link->getAttribute('href'), $this->checked)) {
if (strpos($link->getAttribute('href'), $initialUrl) !== FALSE) {
$this->foundUrls[] = $link->getAttribute('href');
$this->crawlSite($link->getAttribute('href'), $initialUrl);
} else {
$this->foundUrls[] = $initialUrl . $link->getAttribute('href');
$this->crawlSite($initialUrl . $link->getAttribute('href'), $initialUrl);
}
$this->checked[] = $link->getAttribute('href');
}else{
echo "Already Checked <br>";
flush();
ob_flush();
}
}
return $this->foundUrls;
}
}
更新
将代码更新到更大的站点以演示该问题。还包括我刷新输出缓冲区的尝试之一,我还实现了@Dev Jyoti Behera 的移动回声的建议。
更新 2
感谢建议(如上所述),我现在可以看到正在屏幕上打印的实时文本。然而,我现在遇到了第二个问题,爬虫似乎忽略了 has been checked if 语句,它会一遍又一遍地检查并列出相同的 URL。 /sigh - 老实说,我喜欢编程。
【问题讨论】:
-
您更新的代码包含的左括号多于右括号。如果您只是固定括号的数量,它应该会很好地回响。您也可以将其直接放在
foreach($links as $link) { echo $link->getAttribute('href') . '<br>';之后,但我认为这不会有任何区别。 -
echo count($found);行是否返回 0 以外的值? -
谢谢奇瑞尔。 @EatPeanutButter 在一个小站点上,就像问题中提到的那样,它返回 4 (在这种情况下是正确的)。然而,在一个更大的网站上,我无法确定,因为我只是得到一个微调器。
-
我看到 $link->getAttribute('href') 在循环内没有改变。在 if-else 语句之前将 echo $link->getAttribute('href') 行移动到循环体的开头是否对您有用?这样,您将能够看到当前正在被抓取的链接。目前编写代码的方式会导致在所有爬取结束后打印链接(这可能需要很长时间)。
-
@Lewis:确实如此。但是,考虑将它添加到 foreach 循环主体的第一行。这样,对于每次迭代和 $link,都会打印一个新值。