昨日使用haipproxy作為代理源,對(duì)知乎
進(jìn)行了數(shù)據(jù)抓取相關(guān)的性能測(cè)試榔幸,測(cè)試效果還不錯(cuò)郎楼,有興趣的可以點(diǎn)擊項(xiàng)目主頁(yè)查看測(cè)試結(jié)果。但是它仍有繼續(xù)優(yōu)化的空間肪笋,所以筆者打算單獨(dú)寫(xiě)一篇文章來(lái)單獨(dú)闡述它現(xiàn)有的IP篩選策略月劈,也就是題目說(shuō)的高可用
策略。而關(guān)于部署的高可用后續(xù)文章會(huì)談及到藤乙,這里暫時(shí)按下不表猜揪。
下文主要會(huì)談到校驗(yàn)器和客戶(hù)端的IP篩選策略。
校驗(yàn)器
我們知道坛梁,一個(gè)代理IP有多個(gè)屬性而姐,比如成功請(qǐng)求率、響應(yīng)速度划咐、是否支持Get/Post方法拴念、是否匿名和該IP所處位置等钧萍。這些往往也是衡量一個(gè)IP質(zhì)量的可參照標(biāo)準(zhǔn)。而從互聯(lián)網(wǎng)上采集的免費(fèi)IP大多數(shù)是短效的政鼠,所以代理IP對(duì)應(yīng)的最近驗(yàn)證時(shí)間也是一個(gè)很重要的參考標(biāo)準(zhǔn)风瘦。haipproxy目前主要參照請(qǐng)求成功率
、響應(yīng)速度
公般、最近驗(yàn)證時(shí)間
和是否匿名
這四個(gè)維度對(duì)代理IP進(jìn)行篩選万搔。精力所限,目前還未打算對(duì)IP位置進(jìn)行完善官帘,而IP位置對(duì)于已登錄的賬戶(hù)來(lái)說(shuō)具有比較重要的意義瞬雹。還有一點(diǎn)是,對(duì)于同一個(gè)代理IP刽虹,代理不同網(wǎng)站的效果可能大不相同酗捌,所幸的是,haipproxy
可以根據(jù)自己需求定制校驗(yàn)器
根據(jù)haipproxy架構(gòu)篇的介紹涌哲,我們可以知道haipproxy initvalidator
會(huì)過(guò)濾掉部分透明的代理ip胖缤,另外一個(gè)過(guò)濾透明IP的地方是proxy spiders,它在抓取代理IP的時(shí)候會(huì)直接丟棄透明代理IP膛虫。因此草姻,是否匿名
這個(gè)標(biāo)注我們已經(jīng)實(shí)現(xiàn)了,后續(xù)所有的validated queues
中存儲(chǔ)的都是匿名及高匿IP稍刀。
請(qǐng)求成功率
是以打分的方式來(lái)做的撩独,這樣做的原因是不需要對(duì)歷時(shí)成功請(qǐng)求次數(shù)和失敗請(qǐng)求次數(shù)進(jìn)行記錄和計(jì)算,優(yōu)化了部分性能账月,又可以體現(xiàn)一個(gè)IP的穩(wěn)定性综膀。
那么打分的標(biāo)準(zhǔn)又是怎樣的呢?haipproxy
會(huì)先給定一個(gè)初始分?jǐn)?shù)(5)局齿。當(dāng)成功一次剧劝,我們就對(duì)該代理加1分,為了防止分?jǐn)?shù)短時(shí)間急劇增大抓歼,在分?jǐn)?shù)大于一定閾值(10)后就對(duì)其進(jìn)行更平滑的加分處理讥此,具體為round(10/score, 2)
,這樣谣妻,分?jǐn)?shù)會(huì)越來(lái)越難升高萄喳,但是足夠衡量每個(gè)代理IP的穩(wěn)定性了。當(dāng)失敗一次蹋半,就要分情況處理了他巨。我們知道,很多免費(fèi)代理IP可能短時(shí)間失效,比如代理端口被關(guān)了染突。這種情況下捻爷,haipproxy
會(huì)直接丟棄該代理IP,因?yàn)樗鼪](méi)有繼續(xù)校驗(yàn)的必要性了份企,再對(duì)它進(jìn)行校驗(yàn)只會(huì)增加校驗(yàn)器的負(fù)擔(dān)也榄。但是如果本次校驗(yàn)超時(shí)了,校驗(yàn)器會(huì)將該代理IP減一分薪棒,直到分?jǐn)?shù)為0手蝎,則刪除榕莺。對(duì)于不同分?jǐn)?shù)的IP的選取會(huì)在客戶(hù)端部分進(jìn)行說(shuō)明俐芯。
響應(yīng)速度
這個(gè)標(biāo)準(zhǔn)比較容易評(píng)判,haipproxy
的做法是為校驗(yàn)器爬蟲(chóng)加載一個(gè)profilemiddleware钉鸯,從而獲取到請(qǐng)求成功的代理IP的響應(yīng)時(shí)間吧史。同理,最近校驗(yàn)時(shí)間也比較容易獲取到唠雕,我們使用redis的zset
數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)它贸营。
客戶(hù)端
目前,haipproxy
實(shí)現(xiàn)了兩種形式的客戶(hù)端:squid和py_cli岩睁。前者是語(yǔ)言無(wú)關(guān)的钞脂,它使用squid作為二級(jí)代理,它會(huì)定時(shí)自動(dòng)更新squid配置文件捕儒,以獲取新的可用代理冰啃,獲取的方法和使用py_cli
相同,下面會(huì)講到刘莹。使用squid作為二級(jí)代理的好處是便于服務(wù)化阎毅,同時(shí)是語(yǔ)言無(wú)關(guān)的,我們的爬蟲(chóng)端只需要將代理設(shè)置為http://squid_host:3128
就可以了点弯,不用關(guān)心其它扇调,但是這么做有一點(diǎn)不好的是,它的調(diào)度是輪詢(xún)IP抢肛,并且對(duì)于不可用或者低質(zhì)量IP的處理和反饋是不透明的狼钮。基于這點(diǎn)捡絮,有必要實(shí)現(xiàn)基于不同語(yǔ)言的客戶(hù)端熬芜。
py_cli是haipproxy
代理獲取的python實(shí)現(xiàn)。挑選可用代理的具體做法如下:
根據(jù)配置文件的設(shè)置分別從
validated_queue
锦援、ttl_queue
和speed_queue
中挑選出滿(mǎn)足配置參數(shù)需求的代理再對(duì)其求交集猛蔽,參數(shù)默認(rèn)值是LOWEST_SCORE = 6
、TTL_VALIDATED_RESOURCE = 2
和LONGEST_RESPONSE_TIME = 10
,表示的意思是選擇分?jǐn)?shù)大于6且最近驗(yàn)證時(shí)間在2分鐘以?xún)?nèi)且最長(zhǎng)響應(yīng)時(shí)間不超過(guò)10s的代理曼库。這樣可以對(duì)上述的各個(gè)標(biāo)準(zhǔn)做合理的保證区岗。在上述挑選方式選出來(lái)的代理數(shù)量不足(len(proxies) < len(pool)*2
)的時(shí)候,會(huì)放寬挑選要求毁枯,對(duì)速度和最近驗(yàn)證時(shí)間求交集慈缔,然后和成功率做并集。如果代理數(shù)量還不足种玛,它還會(huì)放低要求藐鹤,對(duì)滿(mǎn)足最近驗(yàn)證時(shí)間和成功率的集合做并集。在爬蟲(chóng)客戶(hù)端調(diào)用
py_cli
的時(shí)候赂韵,代理客戶(hù)端ProxyFetcher
會(huì)首先調(diào)用refresh()
方法娱节,如果ProxyFetcher
中的可用代理量不夠,那么就會(huì)通過(guò)上一步的算法對(duì)IP池進(jìn)行擴(kuò)充祭示,如果數(shù)量足夠肄满,那么就會(huì)根據(jù)代理的調(diào)度策略選取合適的IP進(jìn)行使用。目前共有兩種代理調(diào)度策略质涛。(1)輪詢(xún)策略稠歉。代理池是一個(gè)隊(duì)列結(jié)構(gòu),每次從隊(duì)首拿一個(gè)IP進(jìn)行使用汇陆,如果該IP請(qǐng)求成功怒炸,則放到隊(duì)尾,如果不成功毡代,則需要調(diào)用
ProxyFetcher
的proxy_feedback()
方法將結(jié)果進(jìn)行反饋阅羹。這種策略的好處是IP負(fù)載比較均衡。但是缺點(diǎn)在于月趟,IP質(zhì)量參差不齊灯蝴,有的響應(yīng)時(shí)間很快,有的響應(yīng)時(shí)間很慢孝宗,并且高質(zhì)量的免費(fèi)代理IP的生命周期可能很短穷躁,這樣就無(wú)法充分利用。(2)貪婪策略因妇。使用此種策略的時(shí)候问潭,需要爬蟲(chóng)端對(duì)每次請(qǐng)求的響應(yīng)時(shí)間進(jìn)行記錄,每次使用后調(diào)用proxy_feedback()
方法以決定該代理IP是否繼續(xù)下一次請(qǐng)求的時(shí)候被使用婚被。如果使用某個(gè)代理IP的響應(yīng)時(shí)間低于傳入的response_time
參數(shù)狡忙,那么就會(huì)一直使用它,直到不能用就從代理池中刪除址芯。如果時(shí)間高于了response_time
灾茁,那么它會(huì)把該IP放入隊(duì)尾窜觉。概括起來(lái),該策略就是低質(zhì)量IP輪詢(xún)北专,高質(zhì)量IP一直使用禀挫。
上述便是目前關(guān)于haipproxy的代理IP挑選策略的所有細(xì)節(jié)。如果項(xiàng)目對(duì)您有用拓颓,不妨在Github上給個(gè)star语婴。