Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3

前篇回顾:下载一个类型集合的全部图片
本篇目标:获得一个集合页面中所有集合中所有的图片

使用urllib2获取已知集合网页页面的HTML代码,首先使用正则表达式获取本页图片集合的url,根据上篇所写戏在图片集合的函数 def getImgAssemble(url, fileName, filePath): 将集合中所有图片下载到指定文件夹,并将文件夹命名为图片集合标题名,然后判断是否还有下一页。如果有的话则进入下一页进行同样的动作,直到最后一页则集合页面所有图片下载完毕。
本篇将使用threading多线程和线程锁使下载并发执行,以增加效率和运行速度。

有关python多线程:

请自行AOL或百度去。。。。

集合页面url = 'http://desk.zol.com.cn/meinv/'
首先建个函数def getImgCatalog(url, filePath):,然后往里面塞我们需要的东西就好咯。先写好基础到,获取已知url的HTML。
代码如下:
 73 def getImgCatalog(url, filePath):
 74     if not os.path.exists(filePath):
 75         os.makedirs(filePath)
 76     if not filePath.endswith('/'):
 77         filePath += '/'
 78
 79     user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
 80     headers = {'User-Agent' : user_agent}
 81
 82     request = urllib2.Request(url, headers=headers)
 83     content = urllib2.urlopen(request).read().decode('GBK')
 84
 85     f = open('url.txt', 'w')
 86     f.write(content.encode('utf-8'))
 87     f.close()
 88
 89     print content
 90
部分结果如下:
Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第1张图片

接下来我们可以使用正则表达式从HTML中提取我们需要的信息啦。
根据上篇我们所写下载集合图集的函数 def  getImgAssemble(url, fileName, filePath):和我们的需求,我们需要获取这些信息:
图片集合的url:使用来作为函数getImgAssemble的url
图片集合title:作为函数getImgAssemble的fileName。

OK,爬出本页全部图片暂时需要这些信息。
获取图片集合的url,HTML代码如下:

获取其中url和title的正则表达式为:
''

增加了正则表达式的代码如下:
 73 def getImgCatalog(url, filePath):
 74     if not os.path.exists(filePath):
 75         os.makedirs(filePath)
 76     if not filePath.endswith('/'):
 77         filePath += '/'
 78
 79     user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
 80     headers = {'User-Agent' : user_agent}
 81
 82     request = urllib2.Request(url, headers=headers)
 83     content = urllib2.urlopen(request).read().decode('GBK')
 84
 85     pattern = re.compile('', \
 86             re.S)
 87     imgInfoList = re.findall(pattern, content)
 88
 89     for item in imgInfoList:
 90         sUrl = mUrl + item[0]
 91
 92         print sUrl
 93         print item[1]
 94
结果如下图:
Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第2张图片
我们已经得到了我们想要的结果。
然后再将函数 getImgAssemble加进去。
我们再加一个显示运行时间的函数在main()里面以计算程序运行上时间:
import datetime
startTime = datetime.datetime.now()
endTime = datetime.datetime.now()
print (endTime-startTime).seconds
print "count : %d" %count

增加代码如下:
 74 def getImgCatalog(url, filePath):
 75     if not os.path.exists(filePath):
 76         os.makedirs(filePath)
 77     if not filePath.endswith('/'):
 78         filePath += '/'
 79
 80     user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
 81     headers = {'User-Agent' : user_agent}
 82
 83     request = urllib2.Request(url, headers=headers)
 84     content = urllib2.urlopen(request).read().decode('GBK')
 85
 86     pattern = re.compile('', \
 87             re.S)
 88     imgInfoList = re.findall(pattern, content)
 89
 90     for item in imgInfoList:
 91         sUrl = mUrl + item[0]
 92         getImgAssemble(sUrl, item[1], filePath)
 93
main:
 95 def main():
 96     startTime = datetime.datetime.now()
 97
 98     #img save path
 99     savePath = os.getcwd()
100
101     url = 'http://b.zol-img.com.cn/desk/bizhi/image/7/960x600/1450950428732.jpg'
102     #img name4
103     imgName = 'pic1.jpg'
104     #downloadImg(url, imgName, savePath)
105
106     sUrl = 'http://desk.zol.com.cn/bizhi/6128_75825_2.html'
107     fileName = 'meinv'
108     #getImgAssemble(sUrl, fileName, savePath)
109
110     cUrl = 'http://desk.zol.com.cn/meinv/'
111     getImgCatalog(cUrl, savePath)
112
113     endTime = datetime.datetime.now()
114     print '\ntotal running time : %d s' %(endTime-startTime).seconds
115
结果截图:
Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第3张图片
Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第4张图片
时间用了68s,没有比较就不知道这个时间是长还是短。

下面来加个多线程和线程锁,代码如下:

    import threading
 75 catalogLock = threading.Lock()
 76 def getImgCatalog(url, filePath):
 77     if not os.path.exists(filePath):
 78         os.makedirs(filePath)
 79     if not filePath.endswith('/'):
 80         filePath += '/'
 81
 82     user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
 83     headers = {'User-Agent' : user_agent}
 84
 85     request = urllib2.Request(url, headers=headers)
 86     content = urllib2.urlopen(request).read().decode('GBK')
 87
 88     pattern = re.compile('', \
 89             re.S)
 90     imgInfoList = re.findall(pattern, content)
 91
 92     threads = []
 93     for item in imgInfoList:
 94         sUrl = mUrl + item[0]
 95
 96         #add thread
 97         if catalogLock.acquire():
 98             t = threading.Thread(target=getImgAssemble, args=(sUrl, item[1], filePath))
 99             t.setDaemon(True)
100             threads.append(t)
101             catalogLock.release()
102
103     for i in range(len(threads)):
104         threads[i].start()
105     for i in range(len(threads)):
106         threads[i].join(30)
107
结果如下截图:
Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第5张图片
Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第6张图片
用时15s。可以看出,时间明显减少。
其实中间出了个问题困扰了很久。
有时候跑到中间会假死,然后ctrl+c并不能关闭线程,后来发现join里面加一个timeout就可以了,数值可以随意,但是要设的大一点,因为线程里面下载图片不是按顺序逐个下载的,一个图片可能挂起很长时间才会被下载,而且设置的大小并不影响结果时间,我们只是想把能下载下来的图片全部下载下来就好。
希望有谁能提供解决办法解决假死问题。


接下来判读是否有下一页,有的话获取下一页的url。
有下一个的HTML如下:
Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第7张图片

最后一页的HTML如下截图:
Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第8张图片

其实我们只需要判断是否有’id="pageNext"‘就可以判断是否有下一页了。
如果有’id="pageNext"‘,则利用正则表达式‘’获取到下页的url。


整体代码如下:
#/usr/bin/env python

import os
import re
import urllib
import urllib2
import datetime
import threading

mUrl = 'http://desk.zol.com.cn'

def downloadImg(url, imgName, savePath):
    if savePath == '':
        return 'image save path is nil.'
    if imgName == '':
        return 'image is nil.'
    if url == '':
        return 'url is nil.'

    if not os.path.exists(savePath):
        os.makedirs(savePath)
    if not savePath.endswith('/'):
        savePath += '/'

    savePathName = savePath + imgName
    urllib.urlretrieve(url, savePathName)

    print url

def getImgAssemble(url, fileName, filePath):
    if not os.path.exists(filePath):
        os.makedirs(filePath)
    if not filePath.endswith('/'):
        filePath += '/'
    if not fileName in filePath:
        filePath += fileName

    print '******', url
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers = {'User-Agent' : user_agent}
    
    tmpUrl = url
    while True:
        try:   
            request = urllib2.Request(tmpUrl, headers=headers)
            content = urllib2.urlopen(request).read().decode('GBK')
            imgUrl = re.search('', \
                    content).group(1)
            imgCount = re.search('

.+?.+?(\d+).+?

', \ content).group(1) imgSuffix = re.search('http://.+?\..+?/.+?\.(.+?)$', \ imgUrl).group(1) imgName = fileName + imgCount + '.' + imgSuffix downloadImg(imgUrl, imgName, filePath) nextUrlFlag = re.search('', \ content).group(1) if not "javascript:" in nextUrlFlag: tmpUrl = mUrl + nextUrlFlag continue else: print '\n' break except AttributeError: print 'attributeError' except urllib2.URLError, e: if hasattr(e, 'code'): print e.code if hasattr(e, 'reason'): print e.reason catalogLock = threading.Lock() def getImgCatalog(url, filePath): if not os.path.exists(filePath): os.makedirs(filePath) if not filePath.endswith('/'): filePath += '/' user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' headers = {'User-Agent' : user_agent} tmpUrl = url while True: request = urllib2.Request(tmpUrl, headers=headers) content = urllib2.urlopen(request).read().decode('GBK') pattern = re.compile('', \ re.S) imgInfoList = re.findall(pattern, content) threads = [] for item in imgInfoList: sUrl = mUrl + item[0] #add thread if catalogLock.acquire(): t = threading.Thread(target=getImgAssemble, args=(sUrl, item[1], filePath)) t.setDaemon(True) threads.append(t) catalogLock.release() for i in range(len(threads)): threads[i].start() for i in range(len(threads)): threads[i].join(30) if not 'id="pageNext"' in content: break else: tmpUrl = mUrl + re.search('', \ content).group(1) def main(): startTime = datetime.datetime.now() #img save path savePath = os.getcwd() url = 'http://b.zol-img.com.cn/desk/bizhi/image/7/960x600/1450950428732.jpg' #img name4 imgName = 'pic1.jpg' #downloadImg(url, imgName, savePath) sUrl = 'http://desk.zol.com.cn/bizhi/6128_75825_2.html' fileName = 'meinv' #getImgAssemble(sUrl, fileName, savePath) cUrl = 'http://desk.zol.com.cn/meinv/' cFilePath = savePath+'/meinv' getImgCatalog(cUrl, cFilePath) endTime = datetime.datetime.now() print '\ntotal running time : %d s' %(endTime-startTime).seconds if __name__ == '__main__': main()
运行结果如下 Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第9张图片

Python网络爬虫小试刀——抓取ZOL桌面壁纸图片3_第10张图片


文件总共1.64GB,用时494s,大概3.4Mb/s,网速的话平时迅雷下载会员高速离线下载差不多5Mb/s。
速度来说,还可以吧。

the end
谢谢

下篇预告:获取整个网站所有类型的壁纸

你可能感兴趣的:(python,爬虫)