python 网页爬虫+保存图片+多线程+网络代理

来源:互联网 发布:手机视频加速软件 编辑:程序博客网 时间:2024/05/21 06:13

原文来源:http://blog.csdn.net/kevinkitty_love/article/details/10088925


以前对网页爬虫不了解,感觉非常神奇,但是解开这面面纱,似乎里面的原理并不是很难掌握。首先,明白一个概念,HTTP协议,为什么叫超文本协议。超文本的概念,是所有的数据几乎都使用文本模式传输,包括文字,图像等,然后在一个网页中,需要做的是解析这些字符数据,并还原成原始的文件。

爬虫的概念,是以一个网页作为起点,从中发现更多的链接和数据信息,并依此以树形展开,可以想象成为一颗树,对每一个网页,需要按照需求对数据进行筛选(找图片,呢还是找关键字,或者找音频等),最后,根据筛选出的URL,对数据进行下载。大致步骤为:

网页==》网页树==》筛选信息==》下载

笔者这里就以网页图片作为例子:

比如,一张网页里,可能有很多张图片,首先最基本的是对这一张网页中所有的图片链接要能够识别出来,这里一般的方法是对网页文本根据正规式进行匹配,从而搜集包含图片的链接。eg:reg = r"""src\s*="?(\S+)\.jpg"""。其次,对于这些链接进行文件。看起来很抽象的东西,这两步就能实现。接着,网页树就有点难,需要从网页中找到有用的网页链接,然后对这些连接又一次进行筛选,有点像递归。这里的难点很多,比如,当网页链接数量非常多的时候,如何有效筛选有效连接,如何控制搜索深度,如何分配进程等等。

另外,由于目前很多国外的网站是上不去的,所以,有些网页数据下载需要通过代理;另外,考虑到有些机器性能较好,也实现了多线程的机制。笔者进行了一天的调研,终于调试通过。以下是代码:

[python] view plaincopy
  1. import re  
  2. import os  
  3. import sys  
  4. import time    
  5. import threading  
  6. import socket  
  7. import urllib  
  8. import urllib2  
  9.   
  10.   
  11. server = '127.0.0.1'  
  12. port = '8087'  
  13. timeout = 720  
  14. socket.setdefaulttimeout(timeout)  
  15.   
  16. class timer(threading.Thread): #The timer class is derived from the class threading.Thread    
  17.     def __init__(self, num, interval,dir,url):    
  18.         threading.Thread.__init__(self)    
  19.         self.thread_num = num  
  20.         self.interval = interval    
  21.         self.url = url    
  22.         self.dir = dir    
  23.         self.thread_stop = False    
  24.     def run(self): #Overwrite run() method, put what you want the thread do here    
  25.         #while not self.thread_stop:    
  26.             DownloadImgs(self.interval,self.url,self.dir)  
  27.         #print 'Thread Object(%d), Time:%s' %(self.thread_num, time.ctime())    
  28.         #time.sleep(self.interval)    
  29.     def stop(self):    
  30.         self.thread_stop = True   
  31.   
  32. def getContent(url,type):  
  33.     print(">>start connecting:%s" % url)  
  34.     from urllib2 import Request, urlopen, URLError, HTTPError  
  35.       
  36.     proxy = urllib2.ProxyHandler({'http':'http://127.0.0.1:8087'})   
  37.     opener = urllib2.build_opener(proxy,urllib2.HTTPHandler)   
  38.     urllib2.install_opener(opener)  
  39.     try:  
  40.         urlHandler = urllib2.urlopen(url)  
  41.         headers = urlHandler.info().headers  
  42.         length = 0  
  43.         for header in headers:  
  44.             if header.find('Length') != -1:  
  45.                 length = header.split(':')[-1].strip()  
  46.                 length = int(length)  
  47.         if(type=="img" and length<15000):  
  48.             print(" >>>>>>>>%d" % length)  
  49.             dataStr = 'EOF'  
  50.         else:  
  51.             print(" ++++++++%d" % length)  
  52.             dataStr = urlHandler.read()  
  53.     except HTTPError, e:  
  54.         print 'The server couldn\'t fulfill the request.'  
  55.         print 'Error code: ', e.code  
  56.     except URLError, e:  
  57.         print 'We failed to reach a server.'  
  58.         print 'Reason: ', e.reason  
  59.     else:  
  60. #   print("%s" % dataStr)  
  61. #   f = open("text.txt",'wb')  
  62. #   f.write(dataStr)  
  63. #   f.close()  
  64.         return dataStr  
  65. def DownloadImgs(interval,url,dir):  
  66.     dataStr = getContent(url,"html")  
  67.     print("...:%s" % url)  
  68.     if(os.path.isdir(dir) == False):  
  69.         os.mkdir(dir);  
  70.     reg = r"""src\s*="?(\S+)\.jpg"""  
  71.     imgre = re.compile(reg)  
  72.     imglist = imgre.findall(dataStr)  
  73.     x = 0  
  74.     for imgurl in imglist:  
  75.         imgurl =''.join('%s.jpg' % imgurl)  
  76.         if(imgurl.find('http:')>=0):  
  77.             print ("\tdownloading: %s,%s" % (x,imgurl))  
  78.             imgdata=getContent(imgurl,"img")  
  79.             if(imgdata != 'EOF'):  
  80.                 outputFile = '%s/%s.jpg' % (dir,x)  
  81.                 f = open(outputFile,'wb')  
  82.                 f.write(imgdata)  
  83.                 f.close()  
  84.                 x = x + 1  
  85.         else:  
  86.             print ("\tcannot connect: %s" % imgurl)  
  87.         time.sleep(interval)  
  88.   
  89. url_="http://tieba.baidu.com/p/";  
  90. id=2460150866;  
  91. n=1;  
  92.   
  93. thread=[]  
  94. for i in range(0, n):  
  95.     url=''.join('%s%d' % (url_,id + i))  
  96.     dir=''.join('PIC%d' % (id+i) )  
  97.     print("######dir = %s, id = %d" % (dir,id+i))  
  98.     thread.append(timer(11,dir,url))  
  99. for i in range(0, n):  
  100.     thread[i].start()  
  101.   
  102.   
  103.   
  104. #for i in range(0, n):  
  105. #   url=''.join('%s%d' % (url_,id + i))  
  106. #   dir=''.join('PIC%d' % i)  
  107. #   print("######dir = %s, id = %d" % (dir,id))  
  108. #   DownloadImgs(0.1,url,dir)