多种方法实现python批量下载图片

先来个同步版的:

#!/usr/bin/python
#coding:utf-8
import re
import urllib2
import sys
import os
hds={'User-Agent':'chrome/28.0.1500.72',}
#proxy_h=urllib2.ProxyHandler({'http':'http://127.0.0.1:8087'})
"""如果需要账号密码认证,则需要使用proxy_a=urllib2.HTTPBasicAuthHandler().add_password('realm','host','username','password'),并把proxy_a传入urllib2.bulid_opener的第二个参数"""
#opener=urllib2.build_opener(proxy_h)
#urllib2.install_opener(opener)   
def getHtml(url):
    page=urllib2.urlopen(urllib2.Request(url,None,hds)).read() #读取网页html源码
    return page

def getImg(page):
    r_img=re.compile(r"src=\"((http://|https://|)[\w/\.\-/]*\.(jpg|png|gif))\"",re.I)#编译生成一个正则规则,匹配相对绝对,和多种图片格式
    for URL in  r_img.findall(page):#做一个遍历
        try:
            if not URL[1]:	#当它是相对路径时
                URL=Url+'/'+URL[0]	#把它变成绝对路径
            else:
                URL=URL[0]	#直接是绝对路径
            fileName=URL.split('/')[-1]	#取文件名 
            print URL
            img=urllib2.urlopen(urllib2.Request(URL,None,hds)).read()
            open(fileName,'w').write(img).close()

        except Exception,e:
            pass
if __name__ == '__main__':
    Url=sys.argv[1]
    try:
        os.mkdir('img')
    except OSError,e:
        if e.errno == 17:#如果是文件已经存在,则不做任何操作
            pass
        else:			#如果是其他异常,则打印出异常,并退出程序 
            print e
            sys.exit()
    os.chdir('img')	
    getImg(getHtml(Url))

接下去是多线程版的:

#!/usr/bin/python
#coding:utf-8
import re
import urllib2,urllib,socket
import sys
import os
import time
import threading
hds={'User-Agent':'chrome/28.0.1500.72',}
#proxy_h=urllib2.ProxyHandler({'http':'http://127.0.0.1:8087'})
#opener=urllib2.build_opener(proxy_h)
#urllib2.install_opener(opener)
def getHtml(url):
	page=urllib2.urlopen(urllib2.Request(url,None,hds)).read() #读取网页html源码
	return page
class getImgThread(threading.Thread):
    def __init__(self,imgUrl,fileName):
        threading.Thread.__init__(self)
        self.url=imgUrl
        self.fileName=fileName
    def run(self):
        mutex.acquire()
        print self.url
        mutex.release()
        urllib.urlretrieve(self.url,self.fileName)
if __name__ == '__main__':
    socket.setdefaulttimeout(10)
    Url=sys.argv[1]
    try:
		os.mkdir('img')
    except OSError,e:
		if e.errno == 17:#如果是文件已经存在,则不做任何操作
			pass
		else:			#如果是其他异常,则打印出异常,并退出程序 
			print e
			sys.exit()
    os.chdir('img')	
    page=getHtml(Url)
    r_img=re.compile(r"src=\"((http://|https://|)[\w/\.\-/]*\.(jpg|png|gif))\"",re.I)
    mutex=threading.Lock()
    threads=[]
    for URL in  r_img.findall(page):#做一个遍历
        try:
            if not URL[1]:	#当它是相对路径时
                URL=Url+'/'+URL[0]	#把它变成绝对路径
            else:
                URL=URL[0]	#直接是绝对路径
            fileName=URL.split('/')[-1]	#取文件名 
            threads.append(getImgThread(URL,fileName))

        except Exception,e:
            pass
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    print 'End'

再接下去是异步版的

#!/usr/bin/python
#coding:utf-8
import re
import urllib2
import sys
import os
from twisted.internet import defer,reactor
from twisted.web.client import getPage
hds={'User-Agent':'chrome/28.0.1500.72',}
def getHtml(url):
    page=urllib2.urlopen(urllib2.Request(url,None,hds)).read() #读取网页html源码
    return page

def getImg(page):
    r_img=re.compile(r"src=\"((http://|https://|)[\w/\.\-/]*\.(jpg|png|gif))\"",re.I)#编译生成一个正则规则,匹配相对绝对,和多种图片格式

    imgs=[]
    errors=[]
    urls=r_img.findall(page)

    def saveImg(img,filename):
        fd=open(filename,"wb")
        fd.write(img)
        fd.close()
        imgs.append(filename)

    def getError(_):
        print _
        errors.append(_)

    def getFinished(_):
        if len(errors)+len(imgs)==len(urls):
            reactor.stop()

    for URL in  urls:#做一个遍历
        if not URL[1]:	#当它是相对路径时
            URL=Url+'/'+URL[0]	#把它变成绝对路径
        else:
            URL=URL[0]	#直接是绝对路径
        fileName=URL.split('/')[-1]	#取文件名 
        print URL
        deferred=getPage(URL)
        deferred.addCallback(saveImg,fileName)
        deferred.addErrback(getError)
        deferred.addBoth(getFinished)


if __name__ == '__main__':
    Url=sys.argv[1]
    try:
        os.mkdir('img')
    except OSError,e:
        if e.errno == 17:#如果是文件已经存在,则不做任何操作
            pass
        else:			#如果是其他异常,则打印出异常,并退出程序 
            print e
            sys.exit()
    os.chdir('img')	
    d=getPage(Url)
    d.addCallback(getImg)
    reactor.run()

以上的异步使用了轮询,每次下载一副图片,都要去计算下,成功下载次数+失败下载次数是否等于整个任务数,这样就太累了,用不着,下面的是使用了deferlist的机制,当所有deferred都激活后,则执行结束任务。代码如下:

#!/usr/bin/python
#coding:utf-8
import re
import urllib2
import sys
import os
from twisted.internet import defer,reactor
from twisted.web.client import getPage
hds={'User-Agent':'chrome/28.0.1500.72',}
def getHtml(url):
    page=urllib2.urlopen(urllib2.Request(url,None,hds)).read() #读取网页html源码
    return page

def getImg(page):
    r_img=re.compile(r"src=\"((http://|https://|)[\w/\.\-/]*\.(jpg|png|gif))\"",re.I)#编译生成一个正则规则,匹配相对绝对,和多种图片格式

    urls=r_img.findall(page)
    dlist=[] # deferred列表

    def saveImg(img,filename):
        fd=open(filename,"wb")
        fd.write(img)
        fd.close()

    def getError(_):
        print _
        return None

    def getFinished(_):
        reactor.stop()


    for URL in  urls:#做一个遍历
        if not URL[1]:	#当它是相对路径时
            URL=Url+'/'+URL[0]	#把它变成绝对路径
        else:
            URL=URL[0]	#直接是绝对路径
        fileName=URL.split('/')[-1]	#取文件名 
        print URL
        deferred=getPage(URL,timeout=3)
        dlist.append(deferred)
        deferred.addCallback(saveImg,fileName)
        deferred.addErrback(getError)
    d=defer.DeferredList(dlist)
    d.addBoth(getFinished) # 当列表中的deferred都激活后,才会激活这个


if __name__ == '__main__':
    Url=sys.argv[1]
    try:
        os.mkdir('img')
    except OSError,e:
        if e.errno == 17:#如果是文件已经存在,则不做任何操作
            pass
        else:			#如果是其他异常,则打印出异常,并退出程序 
            print e
            sys.exit()
    os.chdir('img')	
    d=getPage(Url)
    d.addCallback(getImg)
    reactor.run()


你可能感兴趣的:(python)