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

时间:2012-05-28 22:36:57

标签: php parsing screen-scraping simple-html-dom getimagesize

我正在使用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

由于某些图片中的相对网址似乎正在发生。这里的问题是,这会导致脚本崩溃,然后没有加载的图像,我的Ajax框会永远加载。

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

3 个答案:

答案 0 :(得分:1)

问题是图片网址是相对于网站根目录的,因此您的服务器无法理解它们以获取它们并找出它们的大小。您可以参考this question找出如何从相对URL获取绝对URL。

答案 1 :(得分:0)

您尝试进行图像尺寸检查的方法是正确的。

但是,为了使其能够在所有网站上运行,您需要添加某种相对URL解析。

我不知道是否有任何图书馆或类似的图书馆,但这里有一个如何做的快速概述:

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

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

答案 2 :(得分: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属性中测试除域之外的任何匹配,并尝试在那里抛出域,但是没有任何承诺每次都可以使用。我认为有更好的方法...也许有一个默认方法并加载一个带有预定义域的配置&#34;修复&#34;对于麻烦的域名。