python spider code


Python代码   收藏代码
  1. #FileName: toolbox_insight.py  
  2. from sgmllib import SGMLParser  
  3. import threading  
  4. import time  
  5. import urllib2  
  6. import StringIO  
  7. import gzip  
  8. import string  
  9. import os  
  10. #rewrite SGMLParser for start_a  
  11. class Basegeturls(SGMLParser):   #这个Basegeturls类作用是分析下载的网页,把网页中的所有链接放在self.url中。  
  12.     def reset(self):  
  13.         self.url = []  
  14.         SGMLParser.reset(self)  
  15.     def start_a(self, attrs):  
  16.         href = [v for k, v in attrs if k == 'href']  
  17.         if href:  
  18.             self.url.extend(href)  
  19. #for quickly finding  
  20. class Newlist(list):#这个类其实是一个添加了find方法的LIST。当num变量在LIST中,返回True,当不在LIST中,返回False并把num按二分法插入LIST中  
  21.     def find(self, num):  
  22.         l = len(self)  
  23.         first = 0  
  24.         end = l - 1  
  25.         mid = 0  
  26.         if l == 0:  
  27.             self.insert(0,num)  
  28.             return False  
  29.         while first < end:  
  30.             mid = (first + end)/2  
  31.             if num > self[mid]:  
  32.                 first = mid + 1  
  33.             elif num < self[mid]:  
  34.                 end = mid - 1  
  35.             else:  
  36.                 break  
  37.         if first == end:  
  38.             if self[first] > num:  
  39.                 self.insert(first, num)  
  40.                 return False  
  41.             elif self[first] < num:  
  42.                 self.insert(first + 1, num)  
  43.                 return False  
  44.             else:  
  45.                 return True  
  46.         elif first > end:  
  47.             self.insert(first, num)  
  48.             return False  
  49.         else:  
  50.             return True  
  51. #下面的reptile顾名思义是一个爬虫          
  52. class reptile(threading.Thread):  
  53.     #Name:       是爬虫是名字,queue是任务队列,所有的爬虫共用同一个任务队列  
  54.     #从中取出一个任务项进行运行,每个任务项是一个要下载网页的URL  
  55.     #result:     也是一个队列,将下载的网页中包含的URL放入该队列中  
  56.     #inittime:   在本程序中没有用,只是一个为了以后扩展用的  
  57.     #downloadway:是下载的网页存放的路径  
  58.     #configfile: 是配置文件,存放网页的URL和下载下后的路径  
  59.     #maxnum:     每个爬虫有个最大下载量,当下载了这么多网页后,爬虫dead  
  60.     def __init__(self, Name, queue, result, Flcok, inittime = 0.00001, downloadway = 'D:\\bbs\\',configfile = 'D:\\bbs\\conf.txt', maxnum = 10000):  
  61.         threading.Thread.__init__(self, name = Name)  
  62.         self.queue = queue  
  63.         self.result = result  
  64.         self.Flcok = Flcok  
  65.         self.inittime = inittime  
  66.         self.mainway = downloadway  
  67.         self.configfile = configfile  
  68.         self.num = 0          #已下载的网页个数  
  69.         self.maxnum = maxnum  
  70.         os.makedirs(downloadway + self.getName())      #系统调用:在存放网页的文件夹中创建一个以该爬虫name为名字的文件夹  
  71.         self.way = downloadway + self.getName() + '\\'  
  72.     def run(self):  
  73.         opener = urllib2.build_opener()     #创建一个开启器  
  74.         while True:  
  75.             url = self.queue.get()          #从队列中取一个URL  
  76.             if url == None:                 #当取得一个None后表示爬虫结束工作,用于外部方便控制爬虫的生命期  
  77.                 break  
  78.             parser = Basegeturls()          #创建一个网页分析器  
  79.             request = urllib2.Request(url) #网页请求  
  80.             request.add_header('Accept-encoding''gzip')#下载的方式是gzip压缩后的网页,gzip是大多数服务器支持的一种格式  
  81.             try:                                         #这样可以减轻网络压力  
  82.                 page = opener.open(request)#发送请求报文  
  83.                 if page.code == 200:       #当请求成功  
  84.                     predata = page.read() #下载gzip格式的网页  
  85.                     pdata = StringIO.StringIO(predata)#下面6行是实现解压缩  
  86.                     gzipper = gzip.GzipFile(fileobj = pdata)  
  87.                     try:  
  88.                         data = gzipper.read()  
  89.                     except(IOError):  
  90.                         print 'unused gzip'  
  91.                         data = predata#当有的服务器不支持gzip格式,那么下载的就是网页本身  
  92.                     try:  
  93.                         parser.feed(data)#分析网页  
  94.                     except:  
  95.                         print 'I am here'#有的网页分析不了,如整个网页就是一个图片  
  96.                     for item in parser.url:  
  97.                         self.result.put(item)#分析后的URL放入队列中  
  98.                     way = self.way + str(self.num) + '.html'#下面的是网页的保存,不多说了  
  99.                     self.num += 1  
  100.                     file = open(way, 'w')  
  101.                     file.write(data)  
  102.                     file.close()  
  103.                     self.Flcok.acquire()  
  104.                     confile = open(self.configfile, 'a')  
  105.                     confile.write( way + ' ' + url + '\n')  
  106.                     confile.close()  
  107.                     self.Flcok.release()  
  108.                 page.close()  
  109.                 if self.num >= self.maxnum:#达到最大量后退出  
  110.                     break  
  111.             except:  
  112.                 print 'end error'  
  113. #和爬虫一样是个线程类,作用是将爬虫中的result中存入的URL加以处理。只要同一个服务器的网页  
  114. class proinsight(threading.Thread):  
  115.     def __init__(self, queue, list, homepage, inqueue):  
  116.         threading.Thread.__init__(self)  
  117.         self.queue = queue#和爬虫中的result队列是同一个  
  118.         self.list = list#是上面Newlist的对象  
  119.         self.homepage = homepage#主页  
  120.         self.inqueue = inqueue#处理完后的URL的去处  
  121.     def run(self):  
  122.         length = len(self.homepage)  
  123.         while True:  
  124.             item = self.queue.get()  
  125.             if item == None:  
  126.                 break  
  127.             if item[0:4] == '\r\n':  
  128.                 item = item[4:]  
  129.             if item[-1] == '/':  
  130.                 item = item[:-1]  
  131.             if len(item) >= len('http://'and item[0:7] == 'http://':  
  132.                 if len(item) >= length and item[0:length] == self.homepage:  
  133.                     if self.list.find(item) == False:  
  134.                         self.inqueue.put(item)  
  135.             elif item[0:5] == '/java' or item[0:4] == 'java':  
  136.                 pass  
  137.             else:     
  138.                 if item[0] != '/':  
  139.                     item = '/' + item  
  140.                 item = self.homepage + item  
  141.                 if self.list.find(item) == False:  
  142.                     self.inqueue.put(item)  
  143. 下面的是一个主函数过程  
  144. 我下载的网站是http://bbs.hit.edu.cn  
  145. 开始网页是http://bbs.hit.edu.cn/mainpage.php  
  146. #FileName:test  
  147. from toolbox_insight import *  
  148. from Queue import Queue  
  149. import threading  
  150. import sys  
  151. num = int(raw_input('Enter the number of thread:'))  
  152. pnum = int(raw_input('Enter the number of download pages:'))  
  153. mainpage = str(raw_input('The mainpage:'))  
  154. startpage = str(raw_input('Start page:'))  
  155. queue = Queue()  
  156. key = Queue()  
  157. inqueue = Queue()  
  158. list = Newlist()  
  159. thlist = []  
  160. Flock = threading.RLock()  
  161. for i in range(num):  
  162.     th = reptile('th' + str(i), queue, key, Flock)  
  163.     thlist.append(th)  
  164. pro = proinsight(key, list, mainpage, inqueue)  
  165. pro.start()  
  166. for i in thlist:  
  167.     i.start()  
  168. queue.put(startpage)  
  169. for i in range(pnum):  
  170.     queue.put(inqueue.get())  
  171. for i in range(num):  
  172.     queue.put(None)  

你可能感兴趣的:(python spider code)