码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2014-09-10 12:24:30      阅读:386      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   os   io   使用   java   

于是决定用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=string.atof(value)  
            if value<1:  
                value=‘‘  
            else:  
                value=formattime(value)  
      
        if value==‘‘ and output_type==htm:value=   
        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‘‘‘‘‘ 
            onMouseOver\= 
            "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写的多线程 代理服务器 抓取,保存,验证程序【转】

标签:des   style   blog   http   color   os   io   使用   java   

原文地址:http://www.cnblogs.com/b13272012771/p/python.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!