博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python爬图片
阅读量:4300 次
发布时间:2019-05-27

本文共 4315 字,大约阅读时间需要 14 分钟。

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

[python] 
  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++中得默认效果是一样的。

转载地址:http://pavws.baihongyu.com/

你可能感兴趣的文章
h:panelGrid、h:panelGroup标签学习
查看>>
f:facet标签 的用法
查看>>
<h:panelgroup>相当于span元素
查看>>
java中append()的方法
查看>>
必学高级SQL语句
查看>>
经典SQL语句大全
查看>>
Eclipse快捷键 10个最有用的快捷键
查看>>
log日志记录是什么
查看>>
<rich:modelPanel>标签的使用
查看>>
<h:commandLink>和<h:inputLink>的区别
查看>>
<a4j:keeyAlive>的英文介绍
查看>>
关于list对象的转化问题
查看>>
VOPO对象介绍
查看>>
suse创建的虚拟机,修改ip地址
查看>>
linux的挂载的问题,重启后就挂载就没有了
查看>>
docker原始镜像启动容器并创建Apache服务器实现反向代理
查看>>
docker容器秒死的解决办法
查看>>
管理网&业务网的一些笔记
查看>>
openstack报错解决一
查看>>
openstack报错解决二
查看>>