一、背景
爬蟲服務請求量大,為了應對反爬措施,增加爬蟲的爬取效率和代理IP使用率,需要設計一個IP代理池,滿足以下需求:
- 定時任務獲取第三方代理
- 及時剔除IP代理池中失效的IP
- 業務隔離IP
- 若IP未失效,但對某個業務來說,IP被封,需要針對業務,隔離此IP
- 均衡使用IP
- 避免IP使用頻率不均問題
通常選用的地上那方外部代理有:螞蟻代理、阿布雲、訊代理(不建議使用)。這里以訊代理為例。
說說訊代理
實際環境測試過,代理質量差,價格不低,客服態度不好。筆者以公司的名義提需求,價錢好商量,對方直截了當回復,沒這功能,也做不了,愛買不買,呵呵。所以真心不建議使用。
1.1 調用代理API
調用混撥代理API,返回結果
{
"ERRORCODE":"0",
"RESULT":[
{"port":"43617","ip":"222.85.5.118"},
{"port":"43569","ip":"180.122.20.108"},
{"port":"20443","ip":"221.230.254.73"}
]}
二、一些知識點
2.1 代理IP是如何產生的?
ASDL撥號,是一種上網方式,每撥一次號,就會產生一個新的IP。而第三方的IP廠商,通常會買很多撥號VPS服務器,定時撥號來產生新的IP,提供給需要代理的客戶。
三、需求1:及時剔除IP代理池中失效的IP
3.1 超過有效時間,自動失效
每個IP都有固定的有效時間(撥號時間)。IP失效的原理,IP通過ASDL撥號產生,當ASDL重新撥號,則舊IP失效,新IP產生。如3分鍾撥一次號,或3-10分鍾撥一次號,為了保證IP的使用率,通常以最長的失效時間(如有效期3-10分鍾,選10分鍾作為失效時間)。
使用Redis存儲Key-Value,失效時間為最長有效時間。Key為IP+端口。Value為任意固定值。
3.2 檢測失效
檢測時間點
- 獲取到IP時,放入代理池之前
- 在代理池中
通常IP的真正有效時間不是固定的,比如說的有效時間是3分鍾,真實有效時間可能低於3分鍾。這里就需要有一個機制來單獨檢測IP是否有效。
通常的做法是,IP池中的每一個IP都要定時訪問一個固定的測試鏈接,訪問失效則從隊列中剔除。
如何選擇固定的鏈接,有下列幾種要求:
- 測試鏈接的網站要盡可能地穩定
- 返回的內容要盡可能的小
- 網站最好不要有反爬措施
測試鏈接
測試鏈接的一個比較好的方案是,自己提供一個CDN鏈接,鏈接指向一個只有200字符串的txt文本。
最好提供兩個CDN鏈接,同時請求,只要有一個能請求通,就判斷為IP有效。防止一處CDN掛掉,導致所有代理IP被判定為失效。
3.3 偽代碼
獲取代理時
請求API,解析獲取代理列表:
每個代理:
if(isEffectiveIp(ip)){
addIpPool(ip);
}
IP代理池中檢查
獲取當前代理池中所有IP:
if(!isEffectiveIp(ip)){
removeIp(ip);
}
四、需求2:業務隔離IP
4.1 IP隔離判定
錯誤記錄隊列
這里IP調用服務就需要做成一個單獨的服務,其他業務服務都調用該IP服務。每次調用的時候需要上報IP,IP可用或不可用,同時附帶業務名(如business-1)。
IP服務端維持一個隊列記錄,記錄業務與IP的錯誤次數,Key為業務名-IP,Value為錯誤次數,設置一個標准值,若連續錯誤N次,則將此IP放到失效隊列。
失效隊列
失效隊列中,使用set存儲,name為業務名稱,value為失效IP
調用IP服務
業務每次調用IP,首先獲取失效隊列中的IP列表,然后請求時附帶IP列表作為參數,請求不包含失效IP的任意IP。
五、需求3:均衡使用IP
使用zset維持,使用時間戳作為score,zset會以score從小到大排列。
當一個IP被使用,則設置score為當前時間戳,則IP會排到隊尾。
每次獲取IP時,都從隊頭的前N個IP中,選擇一個。