Python爬虫之路——简单网页抓图升级版(增加多线程支持)

经过两个晚上的奋斗,将上一篇文章介绍的爬虫稍微改进了下(Python爬虫之路——简单网页抓图),主要是将获取图片链接任务和下载图片任务用线程分开来处理了,而且这次的爬虫不仅仅可以爬第一页的图片链接的,整个http://desk.zol.com.cn/meinv/下面的图片都会被爬到,而且提供了多种分辨率图片的文件下载,具体设置方法代码注释里面有介绍。

这次的代码仍然有点不足,Ctrl-C无法终止程序,应该是线程无法响应主程序的终止消息导致的,(最好放在后台跑程序)还有线程的分配还可以优化的更好一点,后续会陆续改进.

[python]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #coding: utf-8 #############################################################  
  2. # File Name: main.py  
  3. # Author: mylonly  
  4. # mail: mylonly@gmail.com  
  5. # Created Time: Wed 11 Jun 2014 08:22:12 PM CST  
  6. #########################################################################  
  7. #!/usr/bin/python  
  8.   
  9. import re,urllib2,HTMLParser,threading,Queue,time  
  10.   
  11. #各图集入口链接  
  12. htmlDoorList = []  
  13. #包含图片的Hmtl链接  
  14. htmlUrlList = []  
  15. #图片Url链接Queue  
  16. imageUrlList = Queue.Queue(0)  
  17. #捕获图片数量  
  18. imageGetCount = 0  
  19. #已下载图片数量  
  20. imageDownloadCount = 0  
  21. #每个图集的起始地址,用于判断终止  
  22. nextHtmlUrl = ''  
  23. #本地保存路径  
  24. localSavePath = '/data/1920x1080/'  
  25.   
  26. #如果你想下你需要的分辨率的,请修改replace_str,有如下分辨率可供选择1920x1200,1980x1920,1680x1050,1600x900,1440x900,1366x768,1280x1024,1024x768,1280x800  
  27. replace_str = '1920x1080'  
  28.   
  29. replaced_str = '960x600'  
  30.   
  31. #内页分析处理类  
  32. class ImageHtmlParser(HTMLParser.HTMLParser):  
  33.     def __init__(self):  
  34.         self.nextUrl = ''  
  35.         HTMLParser.HTMLParser.__init__(self)  
  36.     def handle_starttag(self,tag,attrs):  
  37.         global imageUrlList  
  38.         if(tag == 'img' and len(attrs) > 2 ):  
  39.             if(attrs[0] == ('id','bigImg')):  
  40.                 url = attrs[1][1]  
  41.                 url = url.replace(replaced_str,replace_str)  
  42.                 imageUrlList.put(url)  
  43.                 global imageGetCount  
  44.                 imageGetCount = imageGetCount + 1  
  45.                 print url  
  46.         elif(tag == 'a' and len(attrs) == 4):  
  47.             if(attrs[0] == ('id','pageNext'and attrs[1] == ('class','next')):  
  48.                 global nextHtmlUrl    
  49.                 nextHtmlUrl = attrs[2][1];  
  50.   
  51. #首页分析类  
  52. class IndexHtmlParser(HTMLParser.HTMLParser):  
  53.     def __init__(self):  
  54.         self.urlList = []  
  55.         self.index = 0  
  56.         self.nextUrl = ''  
  57.         self.tagList = ['li','a']  
  58.         self.classList = ['photo-list-padding','pic']  
  59.         HTMLParser.HTMLParser.__init__(self)  
  60.     def handle_starttag(self,tag,attrs):  
  61.         if(tag == self.tagList[self.index]):  
  62.             for attr in attrs:  
  63.                 if (attr[1] == self.classList[self.index]):  
  64.                     if(self.index == 0):  
  65.                         #第一层找到了  
  66.                         self.index = 1  
  67.                     else:  
  68.                         #第二层找到了  
  69.                         self.index = 0  
  70.                         print attrs[1][1]  
  71.                         self.urlList.append(attrs[1][1])  
  72.                         break  
  73.         elif(tag == 'a'):  
  74.             for attr in attrs:  
  75.                 if (attr[0] == 'id' and attr[1] == 'pageNext'):  
  76.                     self.nextUrl = attrs[1][1]  
  77.                     print 'nextUrl:',self.nextUrl  
  78.                     break  
  79.   
  80. #首页Hmtl解析器  
  81. indexParser = IndexHtmlParser()  
  82. #内页Html解析器  
  83. imageParser = ImageHtmlParser()  
  84.   
  85. #根据首页得到所有入口链接  
  86. print '开始扫描首页...'  
  87. host = 'http://desk.zol.com.cn'  
  88. indexUrl = '/meinv/'  
  89. while (indexUrl != ''):  
  90.     print '正在抓取网页:',host+indexUrl  
  91.     request = urllib2.Request(host+indexUrl)  
  92.     try:  
  93.         m = urllib2.urlopen(request)  
  94.         con = m.read()  
  95.         indexParser.feed(con)  
  96.         if (indexUrl == indexParser.nextUrl):  
  97.             break  
  98.         else:  
  99.             indexUrl = indexParser.nextUrl  
  100.     except urllib2.URLError,e:  
  101.         print e.reason  
  102.   
  103. print '首页扫描完成,所有图集链接已获得:'  
  104. htmlDoorList = indexParser.urlList  
  105.   
  106. #根据入口链接得到所有图片的url  
  107. class getImageUrl(threading.Thread):  
  108.     def __init__(self):  
  109.         threading.Thread.__init__(self)  
  110.     def run(self):  
  111.         for door in htmlDoorList:  
  112.             print '开始获取图片地址,入口地址为:',door  
  113.             global nextHtmlUrl  
  114.             nextHtmlUrl = ''  
  115.             while(door != ''):  
  116.                 print '开始从网页%s获取图片...'% (host+door)  
  117.                 if(nextHtmlUrl != ''):  
  118.                     request = urllib2.Request(host+nextHtmlUrl)  
  119.                 else:  
  120.                     request = urllib2.Request(host+door)  
  121.                 try:  
  122.                     m = urllib2.urlopen(request)  
  123.                     con = m.read()  
  124.                     imageParser.feed(con)  
  125.                     print '下一个页面地址为:',nextHtmlUrl  
  126.                     if(door == nextHtmlUrl):  
  127.                         break  
  128.                 except urllib2.URLError,e:  
  129.                     print e.reason  
  130.         print '所有图片地址均已获得:',imageUrlList  
  131.   
  132. class getImage(threading.Thread):  
  133.     def __init__(self):  
  134.         threading.Thread.__init__(self)  
  135.     def run(self):  
  136.         global imageUrlList  
  137.         print '开始下载图片...'  
  138.         while(True):  
  139.             print '目前捕获图片数量:',imageGetCount  
  140.             print '已下载图片数量:',imageDownloadCount  
  141.             image = imageUrlList.get()  
  142.             print '下载文件路径:',image  
  143.             try:  
  144.                 cont = urllib2.urlopen(image).read()  
  145.                 patter = '[0-9]*\.jpg';  
  146.                 match = re.search(patter,image);  
  147.                 if match:  
  148.                     print '正在下载文件:',match.group()  
  149.                     filename = localSavePath+match.group()  
  150.                     f = open(filename,'wb')  
  151.                     f.write(cont)  
  152.                     f.close()  
  153.                     global imageDownloadCount  
  154.                     imageDownloadCount = imageDownloadCount + 1  
  155.                 else:  
  156.                     print 'no match'  
  157.                 if(imageUrlList.empty()):  
  158.                     break  
  159.             except urllib2.URLError,e:  
  160.                 print e.reason  
  161.         print '文件全部下载完成...'  
  162.   
  163. get = getImageUrl()  
  164. get.start()  
  165. print '获取图片链接线程启动:'  
  166.   
  167. time.sleep(2)  
  168.   
  169. download = getImage()  
  170. download.start()  
  171. print '下载图片链接线程启动:'  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值