Python爬蟲代理校驗器高擴展性

設(shè)計思想:

一、具體網(wǎng)站具體對待惯悠,請求成功與否與網(wǎng)站的差異很大:

相同的代理不同的網(wǎng)站的會給予不同的反饋靠粪,有的網(wǎng)站能請求成功,但是有的網(wǎng)站卻不行;

所以在這里校驗器接受一個形參url茬底,增強對于不同網(wǎng)站的擴展性;

請求成功未必也能夠返回正確的數(shù)據(jù)获洲;這里有衍生到了校驗多種校驗方式:

二阱表、超時校驗:

此種校驗較為簡單,如果超時了贡珊,那么這個代理就不可用最爬,timeout即可判斷,在校驗器模塊內(nèi)集成超時異常判斷方法即可门岔;

三爱致、隱匿失敗校驗:

有些代理不是高匿代理,那么這些代理加了也和沒加差不多寒随,這里校驗的方式也較為簡單糠悯,為了確保自己是帶著套出去的,那么就得有個判斷妻往,這里校驗器接受一個形參ip逢防,這個形參ip指的是你的公網(wǎng)ip,校驗器內(nèi)部拿著這個ip和和代理查詢網(wǎng)站查詢的數(shù)據(jù)進行對比蒲讯,如果是一樣的那么說明隱匿失斖;提供一個比較好的查詢接口:

http://api.ipify.org
返回就是一個一個字符串形式的ip判帮,不含任何網(wǎng)頁標簽局嘁;

四、服務(wù)器響應(yīng)數(shù)據(jù)有效性的校驗:

有時候雖然你請求成功了晦墙,代理或許也是高匿的悦昵,但是,服務(wù)器返回的有可能一個報錯信息頁面比如 xxxxxx抱歉頁面無法訪問晌畅,所以這一塊就要校驗返回的數(shù)據(jù)是否包含你要的字段但指;

關(guān)于代理池:

最好動態(tài)刷新緩存

如果代理池是動態(tài)的:

需要考慮一個問題,上一次刷新的緩存要不要保留,在代理失敗切換代理的時候是不是直接刷新緩存棋凳;答案是肯定的拦坠,每一次失敗后都刷新緩存,道理很簡單剩岳,代理ip有的時效性非常短贞滨,上一秒有效的不一定下一秒有效;
一方面提供代理池的接口會有校驗拍棕,會過濾掉垃圾代理晓铆,最新返回的是經(jīng)過校驗有效的;
另一反面及時代理池接口沒有加經(jīng)過校驗,其返回的最新數(shù)據(jù)可用心也是比較大的绰播,越新越好骄噪;
提醒:此種每次失敗刷新緩存的方法,適用于接口沒有調(diào)用頻率限制的情況蠢箩。

如果代理池是靜態(tài)的:

還是會有一個問題腰池,是隨機獲取呢,還是遍歷呢忙芒?
隨機比較好,遍歷會有一個問題讳侨,打個比方呵萨,如果第一個代理是有效的,那么每回只會用第一個代理跨跨,因為校驗器設(shè)計上就是如果以上三個校驗都是沒毛病的就返回response;其他的都沒機會了潮峦,對于目標站點來說偽裝度就不夠了,失去了代理的價值勇婴,每次請求都是一個ip那不就被輕易識破了嗎忱嘹!
所以這里用random.choice(),每回都是隨機選一個

關(guān)于代理為空的情況:

解決思路:循環(huán)三次刷新緩存

如果代理池為空那么有兩種解決方式,一種是切換代理池耕渴,另一種是取消代理拘悦;

切換代理池:如果有備用代理池,那么最好是切換代理池了橱脸,
取消代理:如果沒有備用代理池础米,只能取消代理

設(shè)計實現(xiàn):

動態(tài)池:

嘗試失敗就刷新緩存

靜態(tài)池:

分為兩種,一種是純靜態(tài)添诉,一種是限制請求頻率的api代理池屁桑;這邊純靜態(tài)在代碼內(nèi)忽略,函數(shù)設(shè)置形參api接受api;對于限制請求評率的代理池栏赴,先循環(huán)遍歷每一個代理蘑斧,如果全部失敗,再次調(diào)用api遍歷,最多調(diào)用三次竖瘾,如果三次都失敗那么取消代理沟突;

外層循環(huán),
第0層校驗代理池是否為空准浴,如果為空循環(huán)3次刷新緩存事扭;再次失敗,返回無代理響應(yīng)
第一層校驗隱匿是否成功乐横,失敗后求橄,循環(huán)一個代理池的長度;再次失敗葡公,返回無代理響應(yīng)
第二層校驗超時罐农,失敗循環(huán)一個代理池的長度;再次失敗催什,返回無代理響應(yīng)
第三層校驗是否返回正確的數(shù)據(jù)涵亏,如果失敗循環(huán)一個代理池的長度;再次失敗蒲凶,返回無代理響應(yīng)
一共四層校驗
如果所有的校驗都失敗气筋,那么取消代理返回無代理響應(yīng)

提醒:這里的代理api是寫死的,因為不同的api返回的數(shù)據(jù)結(jié)構(gòu)不一樣旋圆,解析規(guī)則不同宠默,所以其他代理api調(diào)用該校驗器需要修改源碼的解析規(guī)則

import requests
import random
"""快代理接口"""

# 代理校驗類
class Proxy_Test:

    # 接受ip,api,field,url,headers='',status=1留個參數(shù)
    def __init__(self,ip,field,url,headers='',status=1):
        # 您的公網(wǎng)ip
        self.ip = ip
        # 您調(diào)用代理池的api
        self.api = 'http://dev.kdlapi.com/api/getproxy/?orderid=(你的賬戶id)&num=10&b_pcchrome=1&b_pcie=1&b_pcff=1&protocol=1&method=2&an_an=1&an_ha=1&sp1=1&sp2=1&sep=1'
        # 您的代理池類型,動態(tài)還是靜態(tài)灵巧;接受參數(shù)類型搀矫,int, 1表示動態(tài)刻肄,0表示靜態(tài)
        self.status = status
        # 您的目標url源碼中瓤球,如果請求成功包含的字段;
        self.field = field
        # 目標站點的url
        self.url = url
        # 目標站點的請求頭
        self.headers = headers
        # 第二層校驗計數(shù)器
        self.num2 = 0
        # 靜態(tài)代理池敏弃,計數(shù)器卦羡,對刷新緩存次數(shù)計數(shù)
        self.num3 = 1

    # 代理校驗,返回response麦到,代理成功返回加代理的response,失敗則無代理response
    def proxy_test(self):
        status = 1
        # 第一層校驗計數(shù)器
        num1 = 0

        # 第三層校驗計數(shù)器
        num4 = 0
        # 第四層校驗計數(shù)器
        num5 = 0
        while True:
            # 刷新緩存
            if status == 1:
                # 返回一個帶有proxies key的json value 為列表虹茶,,隅要,蝴罪,這一塊是寫死的api
                self.proxy_list = requests.get(self.api).text.split('\r\n')
                # print(self.proxy_list)

            try:
                # 第一層校驗代理池是否為空,不為空返回一個隨機proxies
                get_pool = self.get_pool()
                proxies = get_pool['proxies']
                length = get_pool['length']
                print('ok')
                # 判斷是否能低延時高匿成功
                try:
                    # print('高匿不驗了')
                    # 第二層校驗步清,是否高匿成功
                    response_ip = requests.get('http://api.ipify.org',
                                           proxies = proxies,
                                           timeout=4,verify=False).text
                    # 校驗有沒有高匿成功,ip為您本機的公網(wǎng)ip
                    if response_ip == self.ip:
                        1 / 0
                        # 第三層校驗要门,是否超時
                    try:
                        response = self.wrapper_proxy(proxies)
                        # 第四層校驗,是否正確響應(yīng)
                        try:
                            content = response.text
                            # print(content)
                            if self.field in content:
                                print('恭喜虏肾,代理成功!')
                                li = [1,response]
                                return li
                            else:
                                1/0
                        except:
                            li = self.failed_retry(status, length, '正確響應(yīng)校驗')
                            if li:
                                return li
                    except:
                        li = self.failed_retry(status, length, '超時校驗')
                        if li:
                            return li
                except:
                    li = self.failed_retry(status,length,'高匿')
                    if li:
                        return li
            except:
                # 循環(huán)三次刷新緩存
                num1 += 1
                if num1 > 3:
                    # 三次都失敗后欢搜,不使用代理返回response
                    print('代理池為空封豪,不使用代理')
                    response =  self.remove_proxy()
                    li = [0,response]
                    return li
                print("代理數(shù)據(jù)庫為空,循環(huán)刷新------第{}次".format(num1))

    # 返回隨機proxy
    def get_pool(self):
        # 隨機選擇,如果是空拋出異常
        proxy = random.choice(self.proxy_list)
        # 代理池的數(shù)量炒瘟;
        length = len(self.proxy_list)
        # print('代理池長度{}'.format(length))
        proxies = {'http': 'http://{}'.format(proxy)}
        result = {'proxies':proxies,'length':length}
        print(result)
        return result

    # 不設(shè)置代理返回response
    def remove_proxy(self):
        # 通過判斷headers是否傳遞來決定是否加上請求頭
        if self.headers == '':
            response = requests.get(self.url,timeout=20)
            return response
        else:
            response = requests.get(url=self.url,headers = self.headers,timeout=20)
            return response

    # 添加代理請求
    def wrapper_proxy(self,proxies):
        # 通過判斷headers是否傳遞來決定是否加上請求頭
        if self.headers == '':
            response = requests.get(self.url,proxies = proxies,timeout=20)
            return response
        else:
            response = requests.get(url=self.url,headers = self.headers,proxies=proxies,timeout=20)
            return response

    # 第二層以及以后的失敗重試
    def failed_retry(self,status,length,level):

        # 當失敗次數(shù)大于等于代理池的長度的時候吹埠,取消代理返回response
        self.num2 += 1
        print('{}失敗{}次'.format(level,self.num2))
        # 如果是靜態(tài)代理池
        if self.status == 0:
            # 修改status狀態(tài),不刷新緩存
            status = 0
        # 遍歷完靜態(tài)池 有刷新三次緩存的機會,機會用完取消代理返回response
        if status == 0:
            if self.num2 >= length:
                self.num3 += 1
                if self.num3 < 4:
                    status = 1
                    self.num2 = 0
                else:
                    print('{}失敗疮装,取消代理'.format(level))
                    response = self.remove_proxy()
                    li = [0,response]
                    return li
        if status == 1:
            if self.num2 >= length:
                self.num2 = 0
                print('{}失敗缘琅,取消代理'.format(level))
                response = self.remove_proxy()
                li = [0,response]
                return li



if __name__ == '__main__':
    # 接受ip,api,field,url,headers='',status=1留個參數(shù)

    api = 'http://localhost:8899/api/v1/proxies?anonymous=true'
    ip = '211.161.244.119'
    field = '學習網(wǎng)絡(luò)爬蟲'
    url = 'https://blog.csdn.net/winterto1990/article/details/51220307'
    headers = {"Host":"blog.csdn.net",
               "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36"
               }
    proxy = Proxy_Test(ip=ip,field=field,url=url,headers=headers)
    response = proxy.proxy_test()[1]
    print(response.text)



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市廓推,隨后出現(xiàn)的幾起案子刷袍,更是在濱河造成了極大的恐慌,老刑警劉巖樊展,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呻纹,死亡現(xiàn)場離奇詭異,居然都是意外死亡专缠,警方通過查閱死者的電腦和手機雷酪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涝婉,“玉大人哥力,你說我怎么就攤上這事∴胰Γ” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵蟀淮,是天一觀的道長最住。 經(jīng)常有香客問我,道長怠惶,這世上最難降的妖魔是什么涨缚? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮策治,結(jié)果婚禮上脓魏,老公的妹妹穿的比我還像新娘。我一直安慰自己通惫,他們只是感情好茂翔,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著履腋,像睡著了一般珊燎。 火紅的嫁衣襯著肌膚如雪惭嚣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天悔政,我揣著相機與錄音晚吞,去河邊找鬼。 笑死谋国,一個胖子當著我的面吹牛槽地,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播芦瘾,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捌蚊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了旅急?” 一聲冷哼從身側(cè)響起逢勾,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎藐吮,沒想到半個月后溺拱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡谣辞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年迫摔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泥从。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡句占,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出躯嫉,到底是詐尸還是另有隱情纱烘,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布祈餐,位于F島的核電站擂啥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏帆阳。R本人自食惡果不足惜哺壶,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜒谤。 院中可真熱鬧山宾,春花似錦、人聲如沸鳍徽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阶祭。三九已至台妆,卻和暖如春翎猛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背接剩。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工切厘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人懊缺。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓疫稿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鹃两。 傳聞我的和親對象是個殘疾皇子遗座,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)俊扳,斷路器途蒋,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 從三月份找實習到現(xiàn)在,面了一些公司馋记,掛了不少号坡,但最終還是拿到小米、百度梯醒、阿里宽堆、京東、新浪茸习、CVTE畜隶、樂視家的研發(fā)崗...
    時芥藍閱讀 42,246評論 11 349
  • 憂家憂國杜拾遺 安始之亂陷戰(zhàn)機 三吏三別前無古 樹碑立傳千秋記
    水墨悠然閱讀 223評論 8 22
  • 幾天沒見家門口街道掃地的清潔工了。 雖然小心翼翼把垃圾堆成一堆号胚;但是夏天天熱籽慢,熱烘烘的曬得垃圾臭氣熏天,蒼蠅已經(jīng)開...
    粒粒藍雪閱讀 162評論 0 0
  • 跟風是別人先去做了什么事猫胁,我們緊跟在后邊模仿著也去做什么箱亿,大概是這個意思吧,我是這么理解的杜漠。 我只知道我們學習极景,付...
    曲曲_0591閱讀 119評論 0 0