在http://pinterest.com这个网站上,注册后,它有一个add a pin, 当你提交一个网站的URL后,按Find Images时,它可以查找你提交网页上所有图片的(并进行长和宽条件的筛选),整个过程一般在10秒左右。请问这是如何实现的,效率这么高?

2011-02-26 09:01:58

4 Answers

这个也很简单呀,通过PHP的getimagesize()就可以获取远程的图片的宽度和高度,我给你写了一下并封装成了函数,你试试

函数功能:
可以支持http://开头的图片和/开头的绝对地址图片
$url参数可以加http://也可以不加http://
支持定义获取最小宽度和高度到最大宽度和高度的图片

以下代码你运行看看,我这里测试是完全没问题的。速度方面也不是大问题,我抓新浪的首页的所有指定宽高的图片,也就5秒左右。 

<?php /** * 获取远程网址下的所有指定宽度和高度的图片 * @param string $url 网站地址 * @param int $min_width 图片最小宽度 * @param int $min_height 图片最小高度 * @param int $max_width 图片最大宽度 * @param int $max_height 图片最大高度 * @return array 筛选后的图片信息 */ function getImage($url='', $min_width=50, $min_height=50, $max_width=100, $max_height=100){ $result = array(); if(empty($url)){ return array(); } if(strtolower(substr($url, 0, 7)) != 'http://'){ $url = 'http://' . $url; } $content = file_get_contents($url); if(empty($content)){ return array(); } preg_match_all('/<img\s+.*?src="(.*?)".*?>/', $content, $matches); if($matches[1]){ foreach($matches[1] as $image){ //判断以/开头的绝对图片URL地址 if(substr($image, 0, 1) == '/'){ $urls = explode('/', $url); $image = 'http://' . $urls[2] . $image; } $info = @getimagesize($image); if( !empty($info) && $info[0]>intval($min_width) && $info[1]>intval($min_height) && $info[0]<intval($max_width) && $info[1]<intval($max_height) ){ $info['url'] = $image; $result[] = $info; } } } return $result; } //测试 $result = getImage('www.sina.com', 60, 50, 120, 100); if($result){ foreach($result as $img){ echo "图片地址:" . $img['url'] . "<br>"; echo "图片宽度:" . $img[0] . "<br>"; echo "图片高度:" . $img[1] . "<br><br />"; } } ?>
2011-02-26 10:41:57

我的粗浅看法是,我觉得他们可能后台会定期跑一个程序,会抓取各个网站的图片并判断大小,将图片的大小存在他们的数据库里,图片可能不会都存在本地,要是当时抓再判断大小肯定来不及,就算代码写的很好,但网络不给力也是白搭。

2011-02-26 12:37:02

我也提供一个思路,
php获取给定网页中所有的图片地址(不进行图片资源的分析),图片的尺寸由前端JS来处理,php处理页面部分@浪际天涯的方法已经很完美了,只需要处理图片处理的部分,直接返回JS一个图片地址的对象就可以,JS处理部分 

/**
 * 图片头数据加载就绪事件 - 更快获取图片尺寸
 * @version 2011.05.27
 * @author  TangBin
 * @see     http://www.planeart.cn/?p=1121
 * @param   {String}    图片路径
 * @param   {Function}  尺寸就绪
 * @param   {Function}  加载完毕 (可选)
 * @param   {Function}  加载错误 (可选)
 * @example imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
        alert('size ready: width=' + this.width + '; height=' + this.height);
    });
 */

var imgReady = (function () {
    var list = [], intervalId = null, 
    // 用来执行队列
    tick = function () {        
        for (var i = 0; i < list.length; i++) {
            list[i].end ? list.splice(i--, 1) : list[i]();
        };
        !list.length && stop();
    },
    
    // 停止所有定时器队列
    stop = function () {
        clearInterval(intervalId);
        intervalId = null;
    };
 
    return function (url, ready, load, error) {
        var onready, width, height, newWidth, newHeight;
        var img = new Image();
        img.src = url;
        // 如果图片被缓存,则直接返回缓存数据
        if (img.complete) {
            ready.call(img);
            load && load.call(img);
            return;
        };
        width = img.width;
        height = img.height;
        // 加载错误后的事件
        img.onerror = function () {
            error && error.call(img);
            onready.end = true;
            img = img.onload = img.onerror = null;
        };
        // 图片尺寸就绪
        onready = function () {
            newWidth = img.width;
            newHeight = img.height;
            if (newWidth !== width || newHeight !== height ||
                // 如果图片已经在其他地方加载可使用面积检测
                newWidth * newHeight > 1024
            ) {
                ready.call(img);
                onready.end = true;
            };
        };
        onready();
        // 完全加载完毕的事件
        img.onload = function () {
            // onload在定时器时间差范围内可能比onready快
            // 这里进行检查并保证onready优先执行
            !onready.end && onready();
            load && load.call(img);
            // IE gif动画会循环执行onload,置空onload即可
            img = img.onload = img.onerror = null;
        }; 
        // 加入队列中定期执行
        if (!onready.end) {
            list.push(onready);
            // 无论何时只允许出现一个定时器,减少浏览器性能损耗
            if (intervalId === null) intervalId = setInterval(tick, 40);
        };
    };
})();

图片预加载JS转自再谈javascript图片预加载技术

  
var width = 200; var height = 200; var valiad_images = []; $.ajax({ type:'get', data:'url='+encodeURI(url), url:'***',//获取图片的程序地址, success:function(data){ var res = $.parseJSON(data); /* [0: "http://s.huffpost.com/images/v/logos/v4/homepage.gif?v9", 1: "http://s.huffpost.com/images/v/logos/v4/tagline.gif", 2: "http://s.huffpost.com/images/splash/t_mini-a.png", 3: "http://s.huffpost.com/images/splash/t_mini-a.png", 4: "http://s.huffpost.com/images/splash/t_mini-a.png", 5: "http://s.huffpost.com/images/splash/t_mini-a.png"] */ for(var i in res) { imageReady(res[i],function() { if(this.width > width && this.height > height) { valiad_images.push(res[i]); } } ); } } })
2011-02-26 14:34:17

这个我正好做过,如果要提高筛选效率,最好的办法应该是将这一步放到浏览器里面通过JS来进行。
具体步骤:
1、通过服务端脚本(比如php)将整个目标网页抓取并返回给浏览器;
2、用正则表达式甄选出所有的图片标签;
3、JS判断图片大小,筛选出目标尺寸的图片。 

2011-02-26 16:06:17
您不能回答该问题或者回答已经关闭!

相关文章推荐

  • C#中using指令的几种用法

    using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到

  • C#实例解析适配器设计模式

    将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作

  • C#开发高性能Log Help类设计开发

    项目中要在操作数据库的异常处理中加入写Log日志,对于商业上有要求,写log时对其它操作尽可能影响小,不能因为加入log导致耗时太多

  • 使用托管C++粘合C#和C++代码(二)

    本文实现一下C++代码调用C#代码的过程。我构造一个简单并且直观的例子:通过C++ UI 触发C# UI.

  • Async和Await使异步编程更简单

    C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作

  • C#开发中的反射机制

    反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等

  • C#运行时相互关系

    C#运行时相互关系,包括运行时类型、对象、线程栈和托管堆之间的相互关系,静态方法、实例方法和虚方法的区别等等

  • C#协变和逆变

    “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型,“逆变”则是指能够使用派生程度更小的类型

  • C#基础概念之延迟加载

    延迟加载(lazy load)是Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作

  • 使用托管C++粘合C#和C++代码(一)

    C#在xml读写,数据库操纵,界面构造等很多方面性能卓越;C++的效率高,是底层开发的必备武器

  • C#中的索引器的简单理解和用法

    C#中的类成员可以是任意类型,包括数组和集合。当一个类包含了数组和集合成员时,索引器将大大简化对数组或集合成员的存取操作

  • 深入C# 序列化(Serialize)、反序列化(Deserialize)

    C#中的序列化和反序列化,序列化是.NET运行时环境用来支持用户定义类型的流化的机制