使用requests下载图片的简单小测试

最近有些小的图像处理的想法,准备用python去实现,其中的第一步就是收集图像了。比较专业的爬虫scrapy太过强大,用来爬图片感觉有些大才小用,前一阵子一直用urllib和cStringIO配合着根据图像的url下载,最近看到了requests库,看文档介绍,使用起来比较方便,于是开始使用requests来下载图片。

在Stackoverflow上,搜到了How to download image using requests,看了下答案,得票最高的两个方法看起来还是略略有些复杂。看到第四个答案时,见到里面还用profile进行了性能分析(看评论,里面有个地方的设置不合理),于是就想简单的把几个方法整体做个比较.

代码比较简单,使用了四个方法:

  • 使用requests里面的iter_content,其中iter_content里的参数chunk_size默认为1,需要设置才会有好的效果;
  • 配合StringIO使用;
  • 据说cStringIO比StringIO性能好,也就做下测试;
  • 直接文件打开,保存,简单粗暴。

具体代码如下:

"""
test different image download profile
"""

import requests
import StringIO
import cStringIO
from PIL import Image
import profile

img_url='http://tvax1.sinaimg.cn/bmiddle/6ba75546jw1ei9nuw4npuj20cs087wfo.jpg'

def test_request():
    img_name = 'request.jpg'

    r = requests.get(img_url)
    with open(img_name, 'wb') as f:
        for chunk in r.iter_content(chunk_size=1024):
            f.write(chunk)

def test_StringIO():
    img_name = 'stringio.jpg'

    r = requests.get(img_url)

    i = Image.open(StringIO.StringIO(r.content))
    i.save(img_name)

def test_cStringIO():
    img_name = 'cstringio.jpg'

    r = requests.get(img_url)

    i = Image.open(cStringIO.StringIO(r.content))
    i.save(img_name)

def test_request1():
    img_name = 'd_req.jpg'

    r = requests.get(img_url)
    with open(img_name,'wb') as f:
        f.write(r.content)

if __name__ == '__main__':
    profile.run('test_request()')
    profile.run('test_StringIO()')
    profile.run('test_cStringIO()')
    profile.run('test_request1()')

一共跑了三次,其中iter_content里的参数chunk_size分别为默认的1,512,1024,结果如下:

99953 function calls (99900 primitive calls) in 0.893 seconds
3777 function calls (3724 primitive calls) in 0.040 seconds
3684 function calls (3631 primitive calls) in 0.060 seconds

从结果可见,chunk_size的大小确实比较重要,默认为1时调用函数快10W次了,速度当然慢了。但貌似也不是越大越好,这个要具体分析了吧。

使用StringIO和cStringIO的结果如下:

StringIO
2979 function calls (2970 primitive calls) in 0.043 seconds
2979 function calls (2970 primitive calls) in 0.033 seconds
2979 function calls (2970 primitive calls) in 0.040 seconds

cStringIO
2486 function calls (2483 primitive calls) in 0.030 seconds
2486 function calls (2483 primitive calls) in 0.030 seconds
2486 function calls (2483 primitive calls) in 0.037 seconds

从结果看,cStringIO确实比StringIO好一些~

简单粗暴的open方法:

2163 function calls (2160 primitive calls) in 0.027 seconds
2163 function calls (2160 primitive calls) in 0.023 seconds
2163 function calls (2160 primitive calls) in 0.020 seconds

果然是最简单的~~其实使用PIL中Image也可以保存图像,但想着现在还不需要图像处理,就不载入Image库了。

OK,先这样,抓图做数据库去~~