【问题标题】:Echo string on each iteration of a foreach loop在 foreach 循环的每次迭代中回显字符串
【发布时间】: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-&gt;getAttribute('href') . '&lt;br&gt;'; 之后,但我认为这不会有任何区别。
  • echo count($found); 行是否返回 0 以外的值?
  • 谢谢奇瑞尔。 @EatPeanutButter 在一个小站点上,就像问题中提到的那样,它返回 4 (在这种情况下是正确的)。然而,在一个更大的网站上,我无法确定,因为我只是得到一个微调器。
  • 我看到 $link->getAttribute('href') 在循环内没有改变。在 if-else 语句之前将 echo $link->getAttribute('href') 行移动到循环体的开头是否对您有用?这样,您将能够看到当前正在被抓取的链接。目前编写代码的方式会导致在所有爬取结束后打印链接(这可能需要很长时间)。
  • @Lewis:确实如此。但是,考虑将它添加到 foreach 循环主体的第一行。这样,对于每次迭代和 $link,都会打印一个新值。

标签: php loops curl


【解决方案1】:

你试过使用 ob_flush() 吗? 这是一个例子。也许这有帮助: https://gist.github.com/jtallant/3260398

【讨论】:

  • 您好,感谢您的回复!是的,我试过了(在我链接的问题的答案中)
猜你喜欢
  • 2018-09-01
  • 1970-01-01
  • 2011-09-27
  • 1970-01-01
  • 2019-09-22
  • 2021-11-03
  • 1970-01-01
  • 2014-05-29
  • 2017-01-15
相关资源
最近更新 更多