- #encoding:utf-8
- import sys
- reload(sys)
- sys.setdefaultencoding('utf8')
- from sgmllib import SGMLParser
- import re
- import urllib
- class URLLister(SGMLParser):
- def start_a(self, attrs):
- url = [v for k, v in attrs if k=='href']
- if url : urll = url[0]
- else : return
- if urll :
- if urll in globalList : return
- if isSou(urll) :
- if sechDir(imgList , urll) > 0 :
- print 'Fetcher page at ' + ' img alredy saved ... ignore . Queue size : '+str(Queue.__len__())
- imgList.append(urll)
- return
- else :
- savImg(urll)
- imgList.append(urll)
- globalList.append(urll)
- print 'Fetcher page at ' + urll + ' save img complete as . Queue size : '+str(Queue.__len__())
- else :
- if sechDir(fetList , urll) > 0 :
- imgList.append(urll)
- return
- else :
- imgList.append(urll)
- enQ(urll)
- print 'Fetcher page at ' + urll + ' a new url , append in Queue . Queue size : '+str(Queue.__len__())
- def unknown_starttag(self , tag , attrs) :
- return
- fetList = [] # list of url listener fetched . 这是非资源url的历史列表,存在于此表中的url将不会再被爬取
- imgList = [] # list of url saved pictures #这是资源url的历史列表,存在于此表中的资源不会再被下载
- rgxStr = r'(http://www.bizhijidi.com/)*/wallpapers/[0-9]*/[0-9]*/[^x00-xff]*-900x1600.jpg' #这是需要下载资源的正则表达式,正则#表达式是啥我就不说了,不知道的自己去面壁。。
- regrgStr = r'^(http://www.bizhijidi.com/)' #这是全局的网址正则匹配式
- staURL = r'http://www.bizhijidi.com/' #这是起始的url
- imgPath = r'/home/zhangjilun/bizhijidi/' #存放图片的本地路径
- Queue = ['http://www.bizhijidi.com/'] #这是url队列,起始时只有起始url在里面
- fileName = [] #filename全局列表。。。暂时木有用。。。留着备用
- globalList = [] #全局url列表,用于第一次筛选url
- #这是动态生成图片文件名的函数,就是取的url里的文件名
- def changeName(url) :
- if url :
- s=url.split('/')
- return s[-1]
- #保存图片的函数,很简单的fileIO
- def savImg(url) :
- if url :
- url = 'http://www.bizhijidi.com' + url
- imgData = urllib2.urlopen(url).read()
- imgName = changeName(url)
- print imgName
- p = imgPath + imgName
- print 'File Path : '+p
- output = open(p,'wb+')
- print 'Saving img ... '
- output.write(imgData)
- output.close()
- return 1
- else :
- return 0
- #判断连接url是否符合站类url正则式,否则为站外连接,会被ignore掉
- def inRange(url) :
- if url :
- #print 'cheak url is inrange : '
- #print regrgStr
- #print url
- m = re.match(regrgStr , url)
- if m : return 1
- else : return 0
- return 0
- #判断url是否是一个资源图片url,同样用正则式实现
- def isSou(url) :
- if url :
- #print 'cheak url is in source : '
- #print url
- m = re.match(rgxStr , url)
- if m : return 1
- else : return 0
- return 0
- #检查列表,如果列表中存在了该url,那么url会被ignore掉
- def sechDir(List , url) :
- if List : return -1
- if url :
- if List.__len__() == 0 :
- List.append(url)
- else :
- if url in List : return 1
- else : return 0
- #入队列函数
- def enQ(url) :
- Queue.insert(0 , url)
- return 1
- #出队列函数
- def deQ() :
- url = Queue.pop()
- print 'Pop url : ' + url
- return url
- #判断队列是否为空
- def cheakQ() :
- if Queue.__len__() != 0 : return 1
- else : return 0
- #最后有一个主方法:
- def readPage(url):
- sock=urllib.urlopen(url)
- listener = URLLister()
- listener.feed(sock.read())
- sock.close()
- listener.close()
- return
- #每弹出一个url,就调用这个主方法。
- #就像这样:
- while cheakQ() != 0 :
- #print 'Reading page ... Queue len : ' + str(Queue.__len__())
- readPage(deQ())
- print 'Fetcher complete ...'
来源: http://www.phpxs.com/code/1005141/