如何仅从 DOM 中抓取最大的图像


How to scrape only the largest images from the DOM?

我正在使用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 框永远加载。

您有任何想法如何解决此问题吗?

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

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

但是,为了使它适用于所有站点,您需要添加某种相对 URL 解析。

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

  • 找到您要抓取的网址的网域部分
  • 假设任何以/开头的 URL 都是绝对 URL。您只需连接域和路径即可获取这些内容
  • 假设任何不以/开头的 URL 都是相对的。您可能需要解析任何 ..用于查找预期路径的 URL 标记
  • 检查文档中的<base>标签:如果文档具有 <base> 标签,它将把所有相对路径锚定到标签中定义的路径中。

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

假设网址为 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 属性中域以外的任何内容的匹配,并尝试将域扔在那里,但没有承诺每次都有效。我认为有更好的方法...也许有一个默认方法,并为麻烦的域加载具有预定义域"修复"的配置。