首页 > 代码库 > python写的多线程 代理服务器 抓取,保存,验证程序【转】

python写的多线程 代理服务器 抓取,保存,验证程序【转】

于是决定用python重新写,python支持多线程啊。
已经有一年多没有用过 python了,很多语法,语言特性都快忘记得差不多了。 经过三天业余时间的
摸索,今天我写的这个程序终于可以和大家交流了。

下面放出源代码: 希望有高手能帮我共同完善, 
这个程序是我学python语言以来写的第二个程序,应该有很多写得不够简洁的地方,希望行家多多指点

程序现有功能:
   1. 能自动从12个网站抓取代理列表,并保存到数据库里面
   2. 自动验证每个代理是否可用,并保存验证时的响应时间做为判断代理速度的依据
   3.  能分类输出代理信息, 已验证的,未验证的,高度匿名代理,普通匿名代理,透明代理到不同文件
   4   支持的输出格式有 xml,htm,csv,txt,tab   每种文件都能自定义字段和格式
   5.  扩展性比较强, 要添加一个新的抓取网站只需要改变一个全局变量,添加两个函数 (有详细接口说明)
   6.   用 sqlite 做数据库,小巧,方便,简单,0配置,0安装,放在屁股口袋里就可以带走
   7.  多线程抓取,多线程验证

我的运行环境:windows xp  + python v2.4 ,其他版本未测试

程序下载:    
代码的注释非常详细,python 初学者都可以看懂, 12个网站抓取分析的正则表达式都有详细注释


 于是决定用python重新写,python支持多线程啊。已经有一年多没有用过 python了,很多语法,语言特性都快忘记得差不多了。 经过三天业余时间的摸索,今天我写的这个程序终于可以和大家交流了。下面放出源代码: 希望有高手能帮我共同完善, 这个程序是我学python语言以来写的第二个程序,应该有很多写得不够简洁的地方,希望行家多多指点程序现有功能:   1. 能自动从12个网站抓取代理列表,并保存到数据库里面   2. 自动验证每个代理是否可用,并保存验证时的响应时间做为判断代理速度的依据   3.  能分类输出代理信息, 已验证的,未验证的,高度匿名代理,普通匿名代理,透明代理到不同文件   4   支持的输出格式有 xml,htm,csv,txt,tab   每种文件都能自定义字段和格式   5.  扩展性比较强, 要添加一个新的抓取网站只需要改变一个全局变量,添加两个函数 (有详细接口说明)   6.   用 sqlite 做数据库,小巧,方便,简单,0配置,0安装,放在屁股口袋里就可以带走   7.  多线程抓取,多线程验证我的运行环境:windows xp  + python v2.4 ,其他版本未测试程序下载:   点击这里(242kb) 代码的注释非常详细,python 初学者都可以看懂, 12个网站抓取分析的正则表达式都有详细注释[python] view plaincopy    # -*- coding: gb2312 -*-      # vi:ts=4:et                """     目前程序能从下列网站抓取代理列表          http://www.cybersyndrome.net/     http://www.pass-e.com/     http://www.cnproxy.com/     http://www.proxylists.net/     http://www.my-proxy.com/     http://www.samair.ru/proxy/     http://proxy4free.com/     http://proxylist.sakura.ne.jp/     http://www.ipfree.cn/     http://www.publicproxyservers.com/     http://www.digitalcybersoft.com/     http://www.checkedproxylists.com/          问:怎样才能添加自己的新网站,并自动让程序去抓取?     答:          请注意源代码中以下函数的定义.从函数名的最后一个数字从1开始递增,目前已经到了13              def build_list_urls_1(page=5):     def parse_page_2(html=‘‘):          def build_list_urls_2(page=5):     def parse_page_2(html=‘‘):          .......          def build_list_urls_13(page=5):     def parse_page_13(html=‘‘):               你要做的就是添加 build_list_urls_14 和 parse_page_14 这两个函数     比如你要从 www.somedomain.com 抓取          /somepath/showlist.asp?page=1         ...  到         /somepath/showlist.asp?page=8  假设共8页          那么 build_list_urls_14 就应该这样定义     要定义这个page这个参数的默认值为你要抓取的页面数8,这样才能正确到抓到8个页面     def build_list_urls_14(page=8):            .....          return [        #返回的是一个一维数组,数组每个元素都是你要抓取的页面的绝对地址             ‘http://www.somedomain.com/somepath/showlist.asp?page=1‘,             ‘http://www.somedomain.com/somepath/showlist.asp?page=2‘,             ‘http://www.somedomain.com/somepath/showlist.asp?page=3‘,             ....             ‘http://www.somedomain.com/somepath/showlist.asp?page=8‘         ]          接下来再写一个函数 parse_page_14(html=‘‘)用来分析上面那个函数返回的那些页面html的内容     并从html中提取代理地址     注意: 这个函数会循环处理 parse_page_14 中的所有页面,传入的html就是那些页面的html文本          ip:   必须为 xxx.xxx.xxx.xxx 数字ip格式,不能为 www.xxx.com 格式     port: 必须为 2-5位的数字     type: 必须为 数字 2,1,0,-1 中的其中一个。这些数字代表代理服务器的类型           2:高度匿名代理  1: 普通匿名代理  0:透明代理    -1: 无法确定的代理类型      #area: 代理所在国家或者地区, 必须转化为 utf8编码格式            def parse_page_14(html=‘‘):         ....         return [             [ip,port,type,area]                      [ip,port,type,area]                      .....                                   ....                                    [ip,port,type,area]                 ]          最后,最重要的一点:修改全局变量 web_site_count的值,让他加递增1  web_site_count=14                    问:我已经按照上面的说明成功的添加了一个自定义站点,我要再添加一个,怎么办?     答:既然已经知道怎么添加 build_list_urls_14 和 parse_page_14了          那么就按照同样的办法添加     def build_list_urls_15(page=5):     def parse_page_15(html=‘‘):          这两个函数,并 更新全局变量   web_site_count=15          """                  import urllib,time,random,re,threading,string            web_site_count=13   #要抓取的网站数目      day_keep=2          #删除数据库中保存时间大于day_keep天的 无效代理      indebug=1                    thread_num=100                   # 开 thread_num 个线程检查代理      check_in_one_call=thread_num*10  # 本次程序运行时 最多检查的代理个数                  skip_check_in_hour=1    # 在时间 skip_check_in_hour内,不对同一个代理地址再次验证      skip_get_in_hour=8      # 每次采集新代理的最少时间间隔 (小时)            proxy_array=[]          # 这个数组保存将要添加到数据库的代理列表       update_array=[]         # 这个数组保存将要更新的代理的数据             db=None                 #数据库全局对象      conn=None      dbfile=proxier.db     #数据库文件名            target_url="http://www.baidu.com/"   # 验证代理的时候通过代理访问这个地址      target_string="030173"               # 如果返回的html中包含这个字符串,      target_timeout=30                    # 并且响应时间小于 target_timeout 秒                                            #那么我们就认为这个代理是有效的                         #到处代理数据的文件格式,如果不想导出数据,请让这个变量为空  output_type=‘‘            output_type=xml                   #以下格式可选,  默认xml                                          # xml                                          # htm                                                     # tab         制表符分隔, 兼容 excel                                          # csv         逗号分隔,   兼容 excel                                          # txt         xxx.xxx.xxx.xxx:xx 格式            # 输出文件名 请保证这个数组含有六个元素      output_filename=[                                            uncheck,             # 对于未检查的代理,保存到这个文件                  checkfail,           # 已经检查,但是被标记为无效的代理,保存到这个文件                  ok_high_anon,        # 高匿代理(且有效)的代理,按speed排序,最块的放前面                  ok_anonymous,        # 普通匿名(且有效)的代理,按speed排序,最块的放前面                  ok_transparent,      # 透明代理(且有效)的代理,按speed排序,最块的放前面                  ok_other             # 其他未知类型(且有效)的代理,按speed排序                  ]                  #输出数据的格式  支持的数据列有        # _ip_ , _port_ , _type_ , _status_ , _active_ ,      #_time_added_, _time_checked_ ,_time_used_ ,  _speed_, _area_                                                    output_head_string=‘‘             # 输出文件的头部字符串      output_format=‘‘                  # 文件数据的格式          output_foot_string=‘‘             # 输出文件的底部字符串                        if   output_type==xml:          output_head_string="<?xml version=‘1.0‘ encoding=‘gb2312‘?><proxylist>\n"           output_format="""<item>                 <ip>_ip_</ip>                 <port>_port_</port>                 <speed>_speed_</speed>                 <last_check>_time_checked_</last_check>                 <area>_area_</area>             </item>                 """          output_foot_string="</proxylist>"      elif output_type==htm:          output_head_string="""<table border=1 width=‘100%‘>             <tr><td>代理</td><td>最后检查</td><td>速度</td><td>地区</td></tr>             """          output_format="""<tr>         <td>_ip_:_port_</td><td>_time_checked_</td><td>_speed_</td><td>_area_</td>         </tr>         """          output_foot_string="</table>"      else:           output_head_string=‘‘          output_foot_string=‘‘            if output_type=="csv":          output_format="_ip_, _port_, _type_,  _speed_, _time_checked_,  _area_\n"            if output_type=="tab":          output_format="_ip_\t_port_\t_speed_\t_time_checked_\t_area_\n"            if output_type=="txt":          output_format="_ip_:_port_\n"                  # 输出文件的函数      def output_file():          global output_filename,output_head_string,output_foot_string,output_type          if output_type==‘‘:              return          fnum=len(output_filename)          content=[]          for i in range(fnum):              content.append([output_head_string])                    conn.execute("select * from `proxier` order by `active`,`type`,`speed` asc")          rs=conn.fetchall()                    for item in rs:              type,active=item[2],item[4]              if   active is None:                  content[0].append(formatline(item))   #未检查              elif active==0:                  content[1].append(formatline(item))   #非法的代理              elif active==1 and type==2:                  content[2].append(formatline(item))   #高匿                 elif active==1 and type==1:                  content[3].append(formatline(item))   #普通匿名                elif active==1 and type==0:                  content[4].append(formatline(item))   #透明代理                           elif active==1 and type==-1:                  content[5].append(formatline(item))   #未知类型的代理              else:                  pass                for i in range(fnum):              content[i].append(output_foot_string)              f=open(output_filename[i]+"."+output_type,w)              f.write(string.join(content[i],‘‘))              f.close()            #格式化输出每条记录      def formatline(item):          global output_format          arr=[_ip_,_port_,_type_,_status_,_active_,              _time_added_,_time_checked_,_time_used_,              _speed_,_area_]          s=output_format          for i  in range(len(arr)):              s=string.replace(s,arr[i],str(formatitem(item[i],i)))          return s                   #对于数据库中的每个不同字段,要处理一下,中文要编码,日期字段要转化      def formatitem(value,colnum):          global output_type          if (colnum==9):              value=value.encode(cp936)          elif value is None:              value=‘‘                if colnum==5 or colnum==6 or colnum==7:      #time_xxxed              value=http://www.mamicode.com/string.atof(value)              if value<1:                  value=‘‘              else:                  value=formattime(value)                if value=http://www.mamicode.com/=‘‘ and output_type==htm:value=http://www.mamicode.com/           return value                        def check_one_proxy(ip,port):          global update_array          global check_in_one_call          global target_url,target_string,target_timeout                    url=target_url          checkstr=target_string          timeout=target_timeout          ip=string.strip(ip)          proxy=ip+:+str(port)          proxies = {http: http://+proxy+/}          opener = urllib.FancyURLopener(proxies)          opener.addheaders = [              (User-agent,Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1))              ]          t1=time.time()                if (url.find("?")==-1):              url=url+?rnd=+str(random.random())          else:              url=url+&rnd=+str(random.random())                try:              f = opener.open(url)              s= f.read()                   pos=s.find(checkstr)          except:              pos=-1              pass          t2=time.time()            timeused=t2-t1          if (timeused<timeout and pos>0):              active=1          else:              active=0              update_array.append([ip,port,active,timeused])          print len(update_array), of ,check_in_one_call," ",ip,:,port,--,int(timeused)                      def get_html(url=‘‘):          opener = urllib.FancyURLopener({})      #不使用代理          #www.my-proxy.com 需要下面这个Cookie才能正常抓取          opener.addheaders = [                  (User-agent,Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)),                  (Cookie,permission=1)                  ]          t=time.time()          if (url.find("?")==-1):              url=url+?rnd=+str(random.random())          else:              url=url+&rnd=+str(random.random())          try:              f = opener.open(url)              return f.read()               except:              return ‘‘                                     ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                  def build_list_urls_1(page=5):          page=page+1          ret=[]          for i in range(1,page):              ret.append(http://proxy4free.com/page%(num)01d.html%{num:i})                  return ret            def parse_page_1(html=‘‘):          matches=re.findall(r‘‘‘‘‘                 <td>([\d\.]+)<\/td>[\s\n\r]*   #ip                 <td>([\d]+)<\/td>[\s\n\r]*     #port                 <td>([^\<]*)<\/td>[\s\n\r]*    #type                  <td>([^\<]*)<\/td>             #area                  ‘‘‘,html,re.VERBOSE)          ret=[]          for match in matches:              ip=match[0]              port=match[1]              type=match[2]              area=match[3]              if (type==anonymous):                  type=1              elif (type==high anonymity):                  type=2              elif (type==transparent):                  type=0              else:                  type=-1              ret.append([ip,port,type,area])              if indebug:print 1,ip,port,type,area          return ret            ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                        def build_list_urls_2(page=1):          return [http://www.digitalcybersoft.com/ProxyList/fresh-proxy-list.shtml]            def parse_page_2(html=‘‘):          matches=re.findall(r‘‘‘‘‘             ((?:[\d]{1,3}\.){3}[\d]{1,3})\:([\d]+)      #ip:port             \s+(Anonymous|Elite Proxy)[+\s]+            #type             (.+)\r?\n                                   #area             ‘‘‘,html,re.VERBOSE)          ret=[]          for match in matches:              ip=match[0]              port=match[1]              type=match[2]              area=match[3]              if (type==Anonymous):                  type=1              else:                  type=2              ret.append([ip,port,type,area])              if indebug:print 2,ip,port,type,area          return ret                  ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                        def build_list_urls_3(page=15):          page=page+1          ret=[]          for i in range(1,page):              ret.append(http://www.samair.ru/proxy/proxy-%(num)02d.htm%{num:i})                return ret            def parse_page_3(html=‘‘):          matches=re.findall(r‘‘‘‘‘             <tr><td><span\sclass\="\w+">(\d{1,3})<\/span>\. #ip(part1)             <span\sclass\="\w+">                                         (\d{1,3})<\/span>                               #ip(part2)             (\.\d{1,3}\.\d{1,3})                            #ip(part3,part4)                  \:\r?\n(\d{2,5})<\/td>                          #port             <td>([^<]+)</td>                                #type             <td>[^<]+<\/td>                                             <td>([^<]+)<\/td>                               #area             <\/tr>‘‘‘,html,re.VERBOSE)              ret=[]          for match in matches:              ip=match[0]+"."+match[1]+match[2]              port=match[3]              type=match[4]              area=match[5]              if (type==anonymous proxy server):                  type=1              elif (type==high-anonymous proxy server):                  type=2              elif (type==transparent proxy):                  type=0              else:                  type=-1              ret.append([ip,port,type,area])              if indebug:print 3,ip,port,type,area          return ret                        ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                  def build_list_urls_4(page=3):          page=page+1          ret=[]          for i in range(1,page):              ret.append(http://www.pass-e.com/proxy/index.php?page=%(n)01d%{n:i})                  return ret            def parse_page_4(html=‘‘):          matches=re.findall(r"""             list             \(‘(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})‘        #ip             \,‘(\d{2,5})‘                                   #port             \,‘(\d)‘                                        #type             \,‘([^‘]+)‘\)                                   #area             \;\r?\n""",html,re.VERBOSE)           ret=[]          for match in matches:              ip=match[0]              port=match[1]              type=match[2]              area=match[3]              if (type==1):      #type的判断可以查看抓回来的网页的javascript部分                  type=1              elif (type==3):                  type=2              elif (type==2):                  type=0              else:                  type=-1              if indebug:print 4,ip,port,type,area                          area=unicode(area, cp936)               area=area.encode(utf8)                           ret.append([ip,port,type,area])          return ret                  ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                        def build_list_urls_5(page=12):          page=page+1          ret=[]          for i in range(1,page):              ret.append(http://www.ipfree.cn/index2.asp?page=%(num)01d%{num:i})                return ret            def parse_page_5(html=‘‘):          matches=re.findall(r"<font color=black>([^<]*)</font>",html)           ret=[]          for index, match in enumerate(matches):              if (index%3==0):                  ip=matches[index+1]                  port=matches[index+2]                  type=-1      #该网站未提供代理服务器类型                  if indebug:print 5,ip,port,type,match                   area=unicode(match, cp936)                   area=area.encode(utf8)                   ret.append([ip,port,type,area])                       else:                  continue          return ret            ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                        def build_list_urls_6(page=3):          page=page+1          ret=[]          for i in range(1,page):              ret.append(http://www.cnproxy.com/proxy%(num)01d.html%{num:i})                return ret            def parse_page_6(html=‘‘):          matches=re.findall(r‘‘‘‘‘<tr>             <td>([^&]+)                     #ip             ‌‍             \:([^<]+)                       #port             </td>             <td>HTTP</td>             <td>[^<]+</td>             <td>([^<]+)</td>                #area             </tr>‘‘‘,html,re.VERBOSE)           ret=[]          for match in matches:              ip=match[0]              port=match[1]              type=-1          #该网站未提供代理服务器类型              area=match[2]              if indebug:print 6,ip,port,type,area              area=unicode(area, cp936)               area=area.encode(utf8)               ret.append([ip,port,type,area])                return ret                        ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                              def build_list_urls_7(page=1):          return [http://www.proxylists.net/http_highanon.txt]            def parse_page_7(html=‘‘):          matches=re.findall(r(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\:(\d{2,5}),html)           ret=[]          for match in matches:              ip=match[0]              port=match[1]              type=2                       area=--              ret.append([ip,port,type,area])              if indebug:print 7,ip,port,type,area          return ret                        ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                                    def build_list_urls_8(page=1):          return [http://www.proxylists.net/http.txt]            def parse_page_8(html=‘‘):          matches=re.findall(r(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\:(\d{2,5}),html)           ret=[]          for match in matches:              ip=match[0]              port=match[1]              type=-1                       area=--              ret.append([ip,port,type,area])              if indebug:print 8,ip,port,type,area          return ret                        ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                        def build_list_urls_9(page=6):          page=page+1          ret=[]          for i in range(0,page):              ret.append(http://proxylist.sakura.ne.jp/index.htm?pages=%(n)01d%{n:i})               return ret            def parse_page_9(html=‘‘):          matches=re.findall(r‘‘‘‘‘             (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})        #ip             \:(\d{2,5})                                 #port             <\/TD>[\s\r\n]*             <TD>([^<]+)</TD>                            #area             [\s\r\n]*             <TD>([^<]+)</TD>                            #type         ‘‘‘,html,re.VERBOSE)              ret=[]          for match in matches:              ip=match[0]              port=match[1]              type=match[3]                       area=match[2]              if (type==Anonymous):                  type=1              else:                  type=-1              ret.append([ip,port,type,area])              if indebug:print 9,ip,port,type,area          return ret            ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                  def build_list_urls_10(page=5):          page=page+1          ret=[]          for i in range(1,page):              ret.append(http://www.publicproxyservers.com/page%(n)01d.html%{n:i})                  return ret            def parse_page_10(html=‘‘):          matches=re.findall(r‘‘‘‘‘             (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})    #ip             <\/td>[\s\r\n]*             <td[^>]+>(\d{2,5})<\/td>                #port             [\s\r\n]*             <td>([^<]+)<\/td>                       #type             [\s\r\n]*             <td>([^<]+)<\/td>                       #area             ‘‘‘,html,re.VERBOSE)          ret=[]          for match in matches:              ip=match[0]              port=match[1]              type=match[2]                       area=match[3]              if (type==high anonymity):                  type=2              elif (type==anonymous):                  type=1              elif (type==transparent):                  type=0              else:                  type=-1              ret.append([ip,port,type,area])              if indebug:print 10,ip,port,type,area          return ret            ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                              def build_list_urls_11(page=10):          page=page+1          ret=[]          for i in range(1,page):              ret.append(http://www.my-proxy.com/list/proxy.php?list=%(n)01d%{n:i})                ret.append(http://www.my-proxy.com/list/proxy.php?list=s1)              ret.append(http://www.my-proxy.com/list/proxy.php?list=s2)              ret.append(http://www.my-proxy.com/list/proxy.php?list=s3)                  return ret            def parse_page_11(html=‘‘):          matches=re.findall(r(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\:(\d{2,5}),html)           ret=[]                    if (html.find((Level 1))>0):              type=2          elif (html.find((Level 2))>0):              type=1          elif (html.find((Level 3))>0):              type=0          else:              type=-1                for match in matches:              ip=match[0]              port=match[1]              area=--                      ret.append([ip,port,type,area])              if indebug:print 11,ip,port,type,area          return ret            ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                              def build_list_urls_12(page=4):          ret=[]          ret.append(http://www.cybersyndrome.net/plr4.html)          ret.append(http://www.cybersyndrome.net/pla4.html)          ret.append(http://www.cybersyndrome.net/pld4.html)          ret.append(http://www.cybersyndrome.net/pls4.html)          return ret            def parse_page_12(html=‘‘):          matches=re.findall(r‘‘‘‘‘             onm ouseOver\=             "s\(\‘(\w\w)\‘\)"                           #area             \sonMouseOut\="d\(\)"\s?c?l?a?s?s?\=?"?             (\w?)                                       #type                 "?>             (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})        #ip             \:(\d{2,5})                                 #port             ‘‘‘,html,re.VERBOSE)              ret=[]              for match in matches:              ip=match[2]              port=match[3]              area=match[0]              type=match[1]              if (type==A):                  type=2              elif (type==B):                  type=1              else:                  type=0              ret.append([ip,port,type,area])              if indebug:print 12,ip,port,type,area          return ret            ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                        def build_list_urls_13(page=3):          url=http://www.checkedproxylists.com/          html=get_html(url)              matchs=re.findall(r"""             href\=‘([^‘]+)‘>(?:high_anonymous|anonymous|transparent)             \sproxy\slist<\/a>""",html,re.VERBOSE)              return map(lambda x: url+x, matchs)            def parse_page_13(html=‘‘):          html_matches=re.findall(r"eval\(unescape\(‘([^‘]+)‘\)",html)              if (len(html_matches)>0):              conent=urllib.unquote(html_matches[0])          matches=re.findall(r"""<td>(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})<\/td>                 <td>(\d{2,5})<\/td><\/tr>""",conent,re.VERBOSE)                  ret=[]          if   (html.find(<title>Checked Proxy Lists - proxylist_high_anonymous_)>0):              type=2          elif (html.find(<title>Checked Proxy Lists - proxylist_anonymous_)>0):                                   type=1          elif (html.find(<title>Checked Proxy Lists - proxylist_transparent_)>0):              type=0          else:              type=-1                for match in matches:              ip=match[0]              port=match[1]              area=--              ret.append([ip,port,type,area])              if indebug:print 13,ip,port,type,area          return ret            ################################################################################      #      ##        by Go_Rush(阿舜) from http://ashun.cnblogs.com/      #      ################################################################################                              #线程类            class TEST(threading.Thread):          def __init__(self,action,index=None,checklist=None):              threading.Thread.__init__(self)              self.index =index              self.action=action              self.checklist=checklist                def run(self):              if (self.action==getproxy):                  get_proxy_one_website(self.index)              else:                  check_proxy(self.index,self.checklist)                  def check_proxy(index,checklist=[]):          for item in checklist:              check_one_proxy(item[0],item[1])                  def patch_check_proxy(threadCount,action=‘‘):          global check_in_one_call,skip_check_in_hour,conn          threads=[]          if   (action==checknew):        #检查所有新加入,并且从未被检查过的              orderby= `time_added` desc               strwhere= `active` is null           elif (action==checkok):         #再次检查 以前已经验证成功的 代理              orderby= `time_checked` asc               strwhere= `active`=1           elif (action==checkfail):       #再次检查以前验证失败的代理              orderby= `time_checked` asc               strwhere= `active`=0                      else:                            #检查所有的               orderby= `time_checked` asc               strwhere= 1=1                      sql="""                select `ip`,`port` FROM `proxier` where                      `time_checked` < (unix_timestamp()-%(skip_time)01s)                       and %(strwhere)01s                       order by %(order)01s                       limit %(num)01d             """%{     num:check_in_one_call,                   strwhere:strwhere,                      order:orderby,                  skip_time:skip_check_in_hour*3600}          conn.execute(sql)          rows = conn.fetchall()                   check_in_one_call=len(rows)                    #计算每个线程将要检查的代理个数          if len(rows)>=threadCount:              num_in_one_thread=len(rows)/threadCount             else:              num_in_one_thread=1                threadCount=threadCount+1          print "现在开始验证以下代理服务器....."          for index in range(1,threadCount):                   #分配每个线程要检查的checklist,并把那些剩余任务留给最后一个线程                             checklist=rows[(index-1)*num_in_one_thread:index*num_in_one_thread]                   if (index+1==threadCount):                                checklist=rows[(index-1)*num_in_one_thread:]                    t=TEST(action,index,checklist)              t.setDaemon(True)              t.start()              threads.append((t))          for thread in threads:              thread.join(60)                  update_proxies()            #把所有的检查结果更新到数据库                      def get_proxy_one_website(index):          global proxy_array          func=build_list_urls_+str(index)          parse_func=eval(parse_page_+str(index))          urls=eval(func+())          for url in urls:              html=get_html(url)              print url              proxylist=parse_func(html)              for proxy in proxylist:                  ip=string.strip(proxy[0])                  port=string.strip(proxy[1])                  if (re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}{1}quot;).search(ip)):                      type=str(proxy[2])                      area=string.strip(proxy[3])                      proxy_array.append([ip,port,type,area])                  def get_all_proxies():          global web_site_count,conn,skip_get_in_hour                #检查最近添加代理是什么时候,避免短时间内多次抓取          rs=conn.execute("select max(`time_added`) from `proxier` limit 1")          last_add=rs.fetchone()[0]          if (last_add and my_unix_timestamp()-last_add<skip_get_in_hour*3600):                 print """      放弃抓取代理列表!      因为最近一次抓取代理的时间是: %(t)1s      这个时间距离现在的时间小于抓取代理的最小时间间隔: %(n)1d 小时      如果一定要现在抓取代理,请修改全局变量: skip_get_in_hour 的值                 """%{t:formattime(last_add),n:skip_get_in_hour}              return                    print "现在开始从以下"+str(web_site_count)+"个网站抓取代理列表...."          threads=[]          count=web_site_count+1          for index in range(1,count):              t=TEST(getproxy,index)              t.setDaemon(True)              t.start()              threads.append((t))          for thread in threads:              thread.join(60)                   add_proxies_to_db()            def add_proxies_to_db():          global proxy_array          count=len(proxy_array)          for i in range(count):              item=proxy_array[i]              sql="""insert into `proxier` (`ip`,`port`,`type`,`time_added`,`area`) values             (‘"""+item[0]+"‘,"+item[1]+","+item[2]+",unix_timestamp(),‘"+clean_string(item[3])+"‘)"                      try:                  conn.execute(sql)                  print "%(num)2.1f\%\t"%{num:100*(i+1)/count},item[0],":",item[1]              except:                  pass                   def update_proxies():          global update_array          for item in update_array:              sql=‘‘‘‘‘                  update `proxier` set `time_checked`=unix_timestamp(),                      `active`=%(active)01d,                       `speed`=%(speed)02.3f                                       where `ip`=‘%(ip)01s‘ and `port`=%(port)01d                                             ‘‘‘%{active:item[2],speed:item[3],ip:item[0],port:item[1]}              try:                  conn.execute(sql)                  except:                  pass             #sqlite 不支持 unix_timestamp这个函数,所以我们要自己实现      def my_unix_timestamp():          return int(time.time())            def clean_string(s):          tmp=re.sub(r"[‘\,\s\\\/]",  , s)          return re.sub(r"\s+",  , tmp)            def formattime(t):          return time.strftime(%c,time.gmtime(t+8*3600))                  def open_database():          global db,conn,day_keep,dbfile                        try:              from pysqlite2 import dbapi2 as sqlite          except:              print """             本程序使用 sqlite 做数据库来保存数据,运行本程序需要 pysqlite的支持             python 访问 sqlite 需要到下面地址下载这个模块 pysqlite,  272kb             http://initd.org/tracker/pysqlite/wiki/pysqlite#Downloads             下载(Windows binaries for Python 2.x)             """              raise SystemExit                try:              db = sqlite.connect(dbfile,isolation_level=None)                  db.create_function("unix_timestamp", 0, my_unix_timestamp)                conn  = db.cursor()          except:              print "操作sqlite数据库失败,请确保脚本所在目录具有写权限"              raise SystemExit                sql="""            /* ip:     只要纯ip地址(xxx.xxx.xxx.xxx)的代理 */            /* type:   代理类型 2:高匿 1:普匿 0:透明 -1: 未知 */            /* status: 这个字段本程序还没有用到,留在这里作以后扩展*/             /* active: 代理是否可用  1:可用  0:不可用  */             /* speed:  请求相应时间,speed越小说明速度越快 */                   CREATE TABLE IF NOT EXISTS  `proxier` (               `ip` varchar(15) NOT NULL default ‘‘,                   `port` int(6)  NOT NULL default ‘0‘,               `type` int(11) NOT NULL default ‘-1‘,                   `status` int(11) default ‘0‘,                           `active` int(11) default NULL,                          `time_added` int(11)  NOT NULL default ‘0‘,                 `time_checked` int(11) default ‘0‘,                     `time_used` int(11)  default ‘0‘,                           `speed` float default NULL,                            `area` varchar(120) default ‘--‘,      /*  代理服务器所在位置 */               PRIMARY KEY (`ip`)              );             /*             CREATE INDEX IF NOT EXISTS `type`        ON proxier(`type`);             CREATE INDEX IF NOT EXISTS `time_used`   ON proxier(`time_used`);             CREATE INDEX IF NOT EXISTS `speed`       ON proxier(`speed`);             CREATE INDEX IF NOT EXISTS `active`      ON proxier(`active`);             */             PRAGMA encoding = "utf-8";      /* 数据库用 utf-8编码保存 */         """          conn.executescript(sql)          conn.execute("""DELETE FROM `proxier`                             where `time_added`< (unix_timestamp()-?)                              and `active`=0""",(day_keep*86400,))                      conn.execute("select count(`ip`) from `proxier`")          m1=conn.fetchone()[0]          if m1 is None:return                conn.execute("""select count(`time_checked`)                              from `proxier` where `time_checked`>0""")          m2=conn.fetchone()[0]                    if m2==0:              m3,m4,m5=0,"尚未检查","尚未检查"          else:              conn.execute("select count(`active`) from `proxier` where `active`=1")              m3=conn.fetchone()[0]              conn.execute("""select max(`time_checked`), min(`time_checked`)                                   from `proxier` where `time_checked`>0 limit 1""")              rs=conn.fetchone()              m4,m5=rs[0],rs[1]              m4=formattime(m4)              m5=formattime(m5)          print """         共%(m1)1d条代理,其中%(m2)1d个代理被验证过,%(m3)1d个代理验证有效。                 最近一次检查时间是:%(m4)1s                 最远一次检查时间是: %(m5)1s         提示:对于检查时间超过24小时的代理,应该重新检查其有效性         """%{m1:m1,m2:m2,m3:m3,m4:m4,m5:m5}                        def close_database():          global db,conn          conn.close()          db.close()          conn=None          db=None            if __name__ == __main__:          open_database()          get_all_proxies()          patch_check_proxy(thread_num)          output_file()           close_database()          print "所有工作已经完成"  

 

python写的多线程 代理服务器 抓取,保存,验证程序【转】