2011-04-09 108 views
1

我想实现类似于此的功能http://www.tineye.com/parse?url=yahoo.com - 允许用户从任何网页上传图像。从网页上传图片

对我来说主要的问题是大量图像的网页需要花费太多时间。

我(使用卷曲或urllib的)根据未来计划在Django这样做:页面

  1. 抓斗HTML(花费大网页约1秒):

    file = urllib.urlopen(requested_url) 
    html_string = file.read() 
    
  2. 使用HTML解析器(BeautifulSoup)解析它,查找img标签,并将所有src图像写入列表。 (大页面也需要大约1秒)

  3. 检查我列表中所有图像的大小,如果它们足够大,则返回它们的json响应(需要非常长的时间约15秒,当图像上有大约80个图像时网页)。下面是函数的代码:


def get_image_size(uri): 
    file = urllib.urlopen(uri) 
    p = ImageFile.Parser() 
    data = file.read(1024) 
    if not data: 
     return None 
    p.feed(data) 
    if p.image: 
     return p.image.size 
    file.close() 
    #not an image 
    return None 

正如你所看到的,我不加载完整的图像来获得它的大小,只有它的1KB。但是当有很多图像时(我为每个找到的图像调用一次这个函数),它仍然需要太多时间。

那么我该如何让它工作得更快?

可能有没有办法对每张图片做出请求?

任何帮助将不胜感激。

谢谢!

+0

什么只是检查在HTTP响应内容长度? – tmg 2011-04-09 19:22:36

+0

是的,我考虑过它,但是我想只显示取决于宽度和高度的图像(例如宽度或高度超过100像素),并且仅知道内容长度很难做到。 – 2011-04-09 22:00:17

回答

1

我能想到的几个最佳化的:

  1. 解析因为你是从流中读取一个文件
  2. 使用SAX解析器(这将是伟大的上述点)
  3. 使用HEAD获取图像的大小
  4. 使用队列来放置您的图像,然后使用几个线程连接并获取文件大小
HEAD请求的

例如:

$ telnet m.onet.pl 80 
Trying 213.180.150.45... 
Connected to m.onet.pl. 
Escape character is '^]'. 
HEAD /_m/33fb7563935e11c0cba62f504d91675f,59,29,134-68-525-303-0.jpg HTTP/1.1 
host: m.onet.pl 

HTTP/1.0 200 OK 
Server: nginx/0.8.53 
Date: Sat, 09 Apr 2011 18:32:44 GMT 
Content-Type: image/jpeg 
Content-Length: 37545 
Last-Modified: Sat, 09 Apr 2011 18:29:22 GMT 
Expires: Sat, 16 Apr 2011 18:32:44 GMT 
Cache-Control: max-age=604800 
Accept-Ranges: bytes 
Age: 6575 
X-Cache: HIT from emka1.m10r2.onet 
Via: 1.1 emka1.m10r2.onet:80 (squid) 
Connection: close 

Connection closed by foreign host. 
+0

感谢提醒我的线程!现在一切工作都以可接受的速度进行(约30次请求的速度提高了10倍)。标记为已接受! – 2011-04-11 18:57:50

1

你可以像使用urllib2.urlopen(我不知道urllib)返回的对象那样使用文件的headers属性。

这是我为它写的一个测试。正如你所看到的那样,它速度很快,但我想有些网站会阻止太多的重复请求。

|milo|laurie|¥ cat test.py 
import urllib2 
uri = "http://download.thinkbroadband.com/1GB.zip" 

def get_file_size(uri): 
    file = urllib2.urlopen(uri) 
    content_header, = [header for header in file.headers.headers if header.startswith("Content-Length")] 
    _, str_length = content_header.split(':') 
    length = int(str_length.strip()) 
    return length 

if __name__ == "__main__": 
    get_file_size(uri) 
|milo|laurie|¥ time python2 test.py 
python2 test.py 0.06s user 0.01s system 35% cpu 0.196 total