先来个同步版的:
#!/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()