php 从 url 获取宽度和高度 >=200 的所有图像更快

Posted

技术标签:

【中文标题】php 从 url 获取宽度和高度 >=200 的所有图像更快【英文标题】:php get all the images from url which width and height >=200 more quicker 【发布时间】:2012-04-19 15:02:53 【问题描述】:

我是类似http://pinterest.comadd a pin之类的函数

如何更快地从 url 获取宽度和高度 >=200 的所有图像? pinterest.com 将完成整个过程将近 10 秒,但我需要 48.64 秒。

require dirname(__FILE__) . '/simple_html_dom.php';
$url = 'http://www.huffingtonpost.com/';
$html = file_get_html($url);
if($html->find('img'))
    foreach($html->find('img') as $element) 
        $size = @getimagesize($element->src);
        if($size[0]>=200&&$size[1]>=200)
            echo $element;
        
    
// cost 48.64 seconds

【问题讨论】:

刚刚得到一个在 7 秒内运行的脚本 -- 仍在测试中 【参考方案1】:

getimagesize() 将首先下载整个图像文件,然后进行分析。通常,您只需要文件的前几百个字节即可获取类型/分辨率详细信息。另外,它将为每张图片使用单独的 http 请求。

经过适当优化的系统会使用部分获取请求来仅获取图像的第一块,并利用 http keep-alives 将 TCP 连接开销降至最低。

【讨论】:

部分获取在此处定义:w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 基本上只是一个普通请求,但带有 Range: 标头来指定您要传输的字节。您可以使用 curl 进行持久的 http 请求:php.net/curl【参考方案2】:

那么从 html 中读取宽度和高度呢?我知道有些图片可能没有这个属性,但也许你可以跳过这个属性小于 200px 的图片。

这只是一个想法,但可能不适合您。

【讨论】:

【参考方案3】:

我认为您使用的操作是使用curl_multi_initparallel 中运行curl 请求,请参阅http://php.net/manual/en/function.curl-multi-init.php 了解更多信息。这样,它的加载速度会更快,并避免所有可能影响速度的带宽问题。

将图像保存到本地临时目录中,而不是直接在本地运行getimagesize(),这比在http://上运行要快得多

希望对你有帮助

编辑 1

注意***

A.并非所有图片都以http 开头

B.并非所有图像都有效

C.创建需要存储图像的temp文件夹

概念证明

require 'simple_html_dom.php';
$url = 'http://www.huffingtonpost.com';
$html = file_get_html ( $url );
$nodes = array ();
$start = microtime ();
$res = array ();

if ($html->find ( 'img' )) 
    foreach ( $html->find ( 'img' ) as $element ) 
        if (startsWith ( $element->src, "/" )) 
            $element->src = $url . $element->src;
        
        if (! startsWith ( $element->src, "http" )) 
            $element->src = $url . "/" . $element->src;
        
        $nodes [] = $element->src;
    


echo "<pre>";
print_r ( imageDownload ( $nodes, 200, 200 ) );
echo "<h1>", microtime () - $start, "</h1>";

function imageDownload($nodes, $maxHeight = 0, $maxWidth = 0) 

    $mh = curl_multi_init ();
    $curl_array = array ();
    foreach ( $nodes as $i => $url ) 
        $curl_array [$i] = curl_init ( $url );
        curl_setopt ( $curl_array [$i], CURLOPT_RETURNTRANSFER, true );
        curl_setopt ( $curl_array [$i], CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)' );
        curl_setopt ( $curl_array [$i], CURLOPT_CONNECTTIMEOUT, 5 );
        curl_setopt ( $curl_array [$i], CURLOPT_TIMEOUT, 15 );
        curl_multi_add_handle ( $mh, $curl_array [$i] );
    
    $running = NULL;
    do 
        usleep ( 10000 );
        curl_multi_exec ( $mh, $running );
     while ( $running > 0 );

    $res = array ();
    foreach ( $nodes as $i => $url ) 
        $curlErrorCode = curl_errno ( $curl_array [$i] );

        if ($curlErrorCode === 0) 
            $info = curl_getinfo ( $curl_array [$i] );
            $ext = getExtention ( $info ['content_type'] );
            if ($info ['content_type'] !== null) 
                $temp = "temp/img" . md5 ( mt_rand () ) . $ext;
                touch ( $temp );
                $imageContent = curl_multi_getcontent ( $curl_array [$i] );
                file_put_contents ( $temp, $imageContent );
                if ($maxHeight == 0 || $maxWidth == 0) 
                    $res [] = $temp;
                 else 
                    $size = getimagesize ( $temp );
                    if ($size [1] >= $maxHeight && $size [0] >= $maxWidth) 
                        $res [] = $temp;
                     else 
                        unlink ( $temp );
                    
                
            
        
        curl_multi_remove_handle ( $mh, $curl_array [$i] );
        curl_close ( $curl_array [$i] );

    

    curl_multi_close ( $mh );
    return $res;


function getExtention($type) 
    $type = strtolower ( $type );
    switch ($type) 
        case "image/gif" :
            return ".gif";
            break;
        case "image/png" :
            return ".png";
            break;

        case "image/jpeg" :
            return ".jpg";
            break;

        default :
            return ".img";
            break;
    


function startsWith($str, $prefix) 
    $temp = substr ( $str, 0, strlen ( $prefix ) );
    $temp = strtolower ( $temp );
    $prefix = strtolower ( $prefix );
    return ($temp == $prefix);

输出

Array
(
    [0] => temp/img8cdd64d686ee6b925e8706fa35968da4.gif
    [1] => temp/img5811155f8862cd0c3e2746881df9cd9f.gif
    [2] => temp/imga597bf04873859a69373804dc2e2c27e.jpg
    [3] => temp/img0914451e7e5a6f4c883ad7845569029e.jpg
    [4] => temp/imgb1c8c4fa88d0847c99c6f4aa17a0a457.jpg
    [5] => temp/img36e5da68a30df7934a26911f65230819.jpg
    [6] => temp/img068c1aa705296b38f2ec689e5b3172b9.png
    [7] => temp/imgfbeca2410b9a9fb5c08ef88dacd46895.png
)
0.076347

谢谢 :)

【讨论】:

这是一个很好的方法,非常感谢。一些麻烦:如何获取原始图像的 url,而不是本地临时文件夹中的输出? 这很容易将$res [] = $temp; 替换为$res [] = $url;,这样就可以了......别忘了unlink 一切 @Baba 请修改此条件if ($size [0] &gt;= $maxHeight &amp;&amp; $size [0] &gt;= $maxWidth)。您可能希望将 $size[0] 更改为 $size[1] 以进行 $maxHeight 比较【参考方案4】:

Reference

使用imagecreatefromstringimagesximagesy,这应该在 30 秒内运行。比 getimagesize() 快一点

function ranger($url)
    $headers = array( "Range: bytes=0-32768" );
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    return curl_exec($curl);
    curl_close($curl);

require dirname(__FILE__) . '/simple_html_dom.php';
$url = 'http://www.huffingtonpost.com/';
$html = file_get_html($url);
if($html->find('img'))
    foreach($html->find('img') as $element) 
        $raw = ranger($element->src);
        $im = @imagecreatefromstring($raw);
        $width = @imagesx($im);
        $height = @imagesy($im);
        if($width>=200&&$height>=200)
            echo $element;
        
    

【讨论】:

以上是关于php 从 url 获取宽度和高度 >=200 的所有图像更快的主要内容,如果未能解决你的问题,请参考以下文章

从 url 获取远程图像的宽度高度

WPF - 从互联网 URL 获取图像宽度/高度

php yii - 如何从 yii 图像组件获取图像宽度和高度属性 [关闭]

使用 PHP 获取 PDF 文件的高度和宽度

PHP按最大宽度和宽度大于高度的地方对图片进行排序

php getimagesize()函数获取图片宽度高度