python爬图片

转载 2015年11月19日 22:27:21

参考了别人的代码。给代码添加了多线程和Queue的结合应用。

[python] view plaincopy
  1. #!/usr/bin/env python  
  2. # -*- coding:utf-8 -*-  
  3.   
  4. ''''' 
  5. Created on 2013-3-21 
  6.  
  7. @author: naughty 
  8. '''  
  9. # author: wklken  
  10.   
  11. from sgmllib import SGMLParser  
  12. import os  
  13. import urllib  
  14. import urllib2  
  15. import urlparse  
  16. from Queue import Queue  
  17. from threading import Thread  
  18.   
  19. save_path = '/home/zoer'  
  20. passUrls = set()  
  21.   
  22. qimg = Queue()  
  23. class URLLister(SGMLParser):  
  24.     def reset(self):  
  25.         SGMLParser.reset(self)  
  26.         self.urls = []  
  27.         self.imgs = []  
  28.     def start_a(self, attrs):  
  29.         href = [ v for k, v in attrs if k == "href" and v.startswith("http")]  
  30.         if href:  
  31.             self.urls.extend(href)  
  32.     def start_img(self, attrs):  
  33.         src = [ v for k, v in attrs if k == "src" and v.startswith("http") ]  
  34.         if src:  
  35.             self.imgs.extend(src)  
  36.   
  37. def get_url_of_page(url, if_img=False):  
  38.     ''''' 
  39.     获取一个页面上的所有链接。 
  40.     if_img:如果为true,则获取的是页面上的所有图片的链接 
  41.     '''  
  42.     urls = []  
  43.     try:  
  44.         f = urllib2.urlopen(url, timeout=3).read()  
  45.         url_listen = URLLister()  
  46.         url_listen.feed(f)  
  47.         if if_img:  
  48.             urls.extend(url_listen.imgs)  
  49.         else:  
  50.             urls.extend(url_listen.urls)  
  51.     except urllib2.URLError, e:  
  52.         print e  
  53.     return urls  
  54.   
  55. def get_page_html(begin_url, depth, main_site_domain):  
  56.     ''''' 
  57.     递归处理页面 
  58.     '''  
  59.     if depth <= 0:  
  60.         return  
  61.     print 'handle ' + begin_url  
  62.     passUrls.add(begin_url)  
  63.     #===========================================================================  
  64.     # 读取本页面上的图片  
  65.     #===========================================================================  
  66.     urls = get_url_of_page(begin_url, True)  
  67.     #===========================================================================  
  68.     # 添加图片到queue  
  69.     #===========================================================================  
  70.     for murl in urls:  
  71.         firstindex = murl.find('?')  
  72.         if firstindex != -1:  
  73.             print firstindex  
  74.             murl = murl[:firstindex]  
  75.         print 'add img url:' + murl  
  76.         qimg.put(murl)  
  77.     #===============================================================================  
  78.     # 读取本页面上的链接  
  79.     #===============================================================================  
  80.     urls = get_url_of_page(begin_url)  
  81.     if urls:  
  82.         for murl in urls:  
  83.             if not murl in passUrls:  
  84.                 get_page_html(murl, depth - 1, main_site_domain)  
  85.   
  86. class DPThread(Thread):  
  87.     ''''' 
  88.     下载线程 
  89.     '''  
  90.     def run3(self):  
  91.         while True:  
  92.             filename = qimg.get()  
  93.             filename = filename.split("/")[-1]  
  94.             #dist = os.path.join(save_path, filename)  
  95.             dist = save_path + '/' + filename  
  96.             print dist  
  97.             print 'try connecting ' + filename  
  98.             if filename.endswith('jpg'or filename.endswith('png'or filename.endswith('gif'or filename.endswith('bmp'or filename.endswith('jpeg'):  
  99.                 print 'downloading ' + filename  
  100.                 dist = dist.replace('\\', '/')  
  101.                 urllib.urlretrieve(filename, dist, None)  
  102.                 print "Done: ", filename  
  103.             qimg.task_done()  
  104.       
  105.     def run(self):  
  106.         while True:  
  107.             murl = qimg.get()  
  108.             print 'one '+murl  
  109.             filename = murl.split("/")[-1]  
  110.             urlopen = urllib.URLopener()  
  111.             try:  
  112.                 fp = urlopen.open(murl)  
  113.                 data = fp.read()  
  114.                 fp.close()  
  115.                 f = open(save_path + "/" + filename, 'w+b')  
  116.                 f.write(data)  
  117.                 f.close()  
  118.             except IOError:  
  119.                 print "download error!" + url  
  120.             qimg.task_done()  
  121.   
  122. if __name__ == "__main__":  
  123.     #===========================================================================  
  124.     # 抓取图片首个页面  
  125.     #===========================================================================  
  126.     url = "http://image.baidu.com"  
  127.     #url='http://bringgooglereaderback.com/'  
  128.     #===========================================================================  
  129.     # 图片保存路径  
  130.     #===========================================================================  
  131.       
  132.     if not os.path.exists(save_path):  
  133.         os.mkdir(save_path)  
  134.     #===========================================================================  
  135.     # 遍历深度  
  136.     #===========================================================================  
  137.     max_depth = 1  
  138.     main_site_domain = urlparse.urlsplit(url).netloc  
  139.     get_page_html(url, max_depth, main_site_domain)  
  140.       
  141.     for i in range(1):  
  142.         t = DPThread()  
  143.         t.setDaemon(True)  
  144.         t.start()  
  145.     qimg.join()  
  146.     print 'end'  

上面代码中有一个run方法和一个run3方法。

run3方法中使用urllib的urlretrieve来读取图片。发现这样速度很慢。所以直接在run方法中用了urllib的URLopener来打开图片地址并读取数据直接写到本地磁盘的文件中。

----------------------------------------------------------------------

遇到严重的问题:

由于一开始线程没有设置成Daemon的,所以即使Queue中没有内容了,脚本还是不会退出。设置成Daemon之后,在Queue中每有内容之后,脚本就会退出了。

---------------------------------------------------------

原因解释如下:

python中得thread的一些机制和C/C++不同:在C/C++中,主线程结束后,其子线程会默认被主线程kill掉。而在python中,主线程结束后,会默认等待子线程结束后,主线程才退出。

python对于thread的管理中有两个函数:join和setDaemon

  • join:如在一个线程B中调用threada.join(),则threada结束后,线程B才会接着threada.join()往后运行。
  • setDaemon:主线程A启动了子线程B,调用b.setDaemaon(True),则主线程结束时,会把子线程B也杀死,与C/C++中得默认效果是一样的。

相关文章推荐

python爬虫(爬游民星空壁纸)_图片损坏问题

__author__ = 'AllenMinD' import requests,urllib from bs4 import BeautifulSoup ans = 1 for page in ...

爬去图片的python代码

  • 2015年07月03日 10:28
  • 460B
  • 下载

Python网络爬虫入门(一)——爬取百度贴吧图片

描述:用Python爬去百度贴吧图片并保存到本地。 本人刚学爬虫还不是很熟练,其中难点在于正则表达式的理解;#-*- coding:utf-8-*- import urllib import re ...
  • MTbaby
  • MTbaby
  • 2017年04月17日 12:43
  • 663

Python3爬虫学习笔记2.2——爬图片-妹子图

有失远迎,今天尝试爬取妹子图妹子图。 让老司机飙车

Python爬虫学习之爬美女图片

最近看机器学习挺火的,然后,想要借助业余时间,来学习Python,希望能为来年找一份比较好的工作。   首先,学习得要有动力,动力,从哪里来呢?肯定是从日常需求之中来。我学Python看网上介绍...

Python 爬某个网站下载图片

#!/usr/bin/python # -*- coding: utf-8 -*- import re import urllib2,urllib import random import sys,...

python爬duitang的摄影类图片

这几天闲着没事,写了个python爬虫,专把堆糖上的摄影类图片爬下来

Python 爬百度贴吧里面的图片 分页分帖子爬取

爬百度贴吧里面的图片 分页获取所有的帖子列表 然后再根据帖子, 按页获取所有的图片 程序不太严格,运行过程可能会崩溃 自行修改链接以及正则表达式等...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:python爬图片
举报原因:
原因补充:

(最多只允许输入30个字)