-2

我正在使用SimpleHTMLDOM来抓取页面(在我以外的服务器中)。

基本实现是

try {
    $html = file_get_html(urldecode(trim($url)));
} catch (Exception $e) {
    echo $url;
}

foreach ($html->find('img') as $element) {
  $src = "";
  $src = $element->src;
    if (preg_match("/\.(?:jpe?g|png)$/i", $src)) {
        $images[] = $src;
    }
}

这很好用,但它会返回页面中的所有图像,包括小头像、图标和按钮图像。我当然想避免这些。

然后我尝试在循环中插入如下

...

if (preg_match("/\.(?:jpe?g|png)$/i", $src)) {
    $size = getimagesize($src);
    if ($size[0] > 200) {
        $images[] = $src;
    }
}
...

这在像http://cnn.com. 但在其他情况下,它会返回许多错误。例如

http://www.huffingtonpost.com/2012/05/27/alan-simpson-republicans_n_1549604.html

给出了一堆错误,比如

<p>Severity: Warning</p>
<p>Message:  getimagesize(/images/snn-logo-comments.png): failed to open stream: No such file or directory
<p>Severity: Warning</p>
<p>Message:  getimagesize(/images/close-gray.png): failed to open stream: No such file or directory

这似乎是由于某些图像中的相对 URL 而发生的。这里的问题是这会使脚本崩溃,然后没有加载任何图像,而我的 Ajax 框将永远加载。

你有任何想法如何解决这个问题吗?

4

3 回答 3

1

问题是图像 URL 是相对于站点根目录的,因此您的服务器无法理解它们来获取它们并找出它们的大小。您可以参考这个问题来弄清楚如何从相对 URL 中获取绝对 URL。

于 2012-05-28T22:41:49.853 回答
0

假设网址为http://somedomain.com ,请尝试类似的操作...

$domain = explode('/', $url);
$domain = $domain[2];

// ... snip ...

if (preg_match("/\.(?:jpe?g|png)$/i", $src)) {
    $size = getimagesize($src);
    if ($size[0] > 200) {
        if(strpos($src, '/', 0) === 0)
            $src = $domain . $src;

        $images[] = $src;
    }
}

这会对一些人有所帮助,但它不会是万无一失的——我想不出有很多域使用 ../../etc 图像的相对路径,但我确信有人是——当然,你可以测试匹配图像的 src 属性中的域以外的任何内容,并尝试将域扔在那里,但也没有每次都有效的承诺。我认为有更好的方法......也许有一个默认方法,并为麻烦的域加载带有预定义域“修复”的配置。

于 2012-05-28T23:21:38.460 回答
0

您尝试使用图像大小检查的方法是正确的。

但是,为了让它在所有站点上工作,您需要添加某种相对 URL 解析。

我不知道是否有任何库或类似的库,但这里有一个关于如何做到这一点的快速概述:

  • 找到您正在抓取的 URL 的域部分
  • 假设任何以 / 开头的 URL 都是绝对 URL。您可以简单地通过连接域和路径来获取这些
  • 假设任何不以 / 开头的 URL 都是相对的。您可能需要解析 URL 中的任何 .. 标记以定位预期路径
  • 检查文档中的标签<base>:如果文档有<base>标签,它将所有相对路径锚定到标签中定义的路径中。

您也许可以找到一个库来将相对路径和绝对路径转换为您可以使用的东西,但在大多数情况下,它们不会考虑<base>最后一点提到的标签。

于 2012-05-28T22:44:00.273 回答