99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁(yè)精彩閱讀爬蟲(chóng)福音:GitHub 超火爆開(kāi)源 IP 代理池
爬蟲(chóng)福音:GitHub 超火爆開(kāi)源 IP 代理池
2022-04-12
收藏

作者:閑歡

來(lái)源:Python 技術(shù)

經(jīng)常有粉絲在后臺(tái)留言,問(wèn):大佬,運(yùn)行你的爬蟲(chóng)程序怎么報(bào)錯(cuò)了?

我讓他把報(bào)錯(cuò)信息發(fā)過(guò)來(lái),看過(guò)之后一聲嘆息。

大多數(shù)粉絲是直接拿著代碼就開(kāi)始運(yùn)行,然后就是等待結(jié)果,完全不去仔細(xì)閱讀和理解源碼,遇到報(bào)錯(cuò)就直接過(guò)來(lái)詢問(wèn)。

多數(shù)爬蟲(chóng)源碼運(yùn)行的報(bào)錯(cuò)都是由于訪問(wèn)目標(biāo)網(wǎng)站過(guò)于頻繁,從而導(dǎo)致目標(biāo)網(wǎng)站返回錯(cuò)誤或者沒(méi)有數(shù)據(jù)返回。

目前大多數(shù)網(wǎng)站都是有反爬措施的,如果 IP 在一定時(shí)間內(nèi) 請(qǐng)求次數(shù)超過(guò)了一定的閾值就會(huì)觸發(fā)反爬措施,拒絕訪問(wèn),也就是我們經(jīng)常聽(tīng)到的“封IP”。

那么怎么解決這個(gè)問(wèn)題呢?

一種解決辦法就是降低訪問(wèn)頻率,訪問(wèn)一次就等待一定時(shí)長(zhǎng),然后再次訪問(wèn)。這種方法對(duì)于反爬措施不嚴(yán)格的網(wǎng)站是有效的。

如果遇到反爬措施嚴(yán)格的網(wǎng)站,訪問(wèn)次數(shù)多了還是會(huì)被封殺。而且有時(shí)候你需要爬取數(shù)據(jù),這種解決辦法會(huì)使獲取數(shù)據(jù)的周期特別長(zhǎng)。

第二種解決辦法就是使用代理 IP。我不斷地切換 IP 訪問(wèn),讓目標(biāo)網(wǎng)站認(rèn)為是不同的用戶在訪問(wèn),從而繞過(guò)反爬措施。這也是最常見(jiàn)的方式。

接著,我們又面臨一個(gè)問(wèn)題:哪來(lái)這么多獨(dú)立 IP 地址呢?

最省事的方式當(dāng)然是花錢買服務(wù),這種花錢買到的 IP 一般都是比較穩(wěn)定可靠的。

今天我們來(lái)聊一下不花錢免費(fèi)獲取代理 IP 的方式。

ProxyPool 簡(jiǎn)介

ProxyPool 是一個(gè)爬蟲(chóng)的代理 IP 池,主要功能為定時(shí)采集網(wǎng)上發(fā)布的免費(fèi)代理驗(yàn)證入庫(kù),定時(shí)驗(yàn)證入庫(kù)的代理保證代理的可用性,提供API和CLI兩種使用方式。

同時(shí)你也可以擴(kuò)展代理源以增加代理池IP的質(zhì)量和數(shù)量。

獲取項(xiàng)目

我們可以通過(guò)兩種方式獲取 ProxyPool 項(xiàng)目。

第一種是通過(guò)命令行下載:

git clone git@github.com:jhao104/proxy_pool.git

第二種是下載對(duì)應(yīng)的 zip 壓縮包:

爬蟲(chóng)福音:GitHub 超火爆開(kāi)源 IP 代理池

安裝依賴

我們獲取到項(xiàng)目之后,進(jìn)入到項(xiàng)目的根目錄,運(yùn)行下面的代碼來(lái)安裝項(xiàng)目所需的依賴包:

pip install -r requirements.txt

修改配置文件

要在本地運(yùn)行項(xiàng)目,我們需要針對(duì)本地環(huán)境修改一些配置。打開(kāi)項(xiàng)目中的 setting.py 這個(gè)文件,根據(jù)自己本地的環(huán)境和要求修改配置。

# setting.py 為項(xiàng)目配置文件 # 配置API服務(wù) HOST = "0.0.0.0" # IP PORT = 5000 # 監(jiān)聽(tīng)端口 # 配置數(shù)據(jù)庫(kù) DB_CONN = 'redis://:pwd@127.0.0.1:8888/0' # 配置 ProxyFetcher PROXY_FETCHER = [ "freeProxy01", # 這里是啟用的代理抓取方法名,所有fetch方法位于fetcher/proxyFetcher.py "freeProxy02", # .... ]

主要修改的幾項(xiàng)配置是監(jiān)聽(tīng)端口(PORT)、 Redis 數(shù)據(jù)庫(kù)的配置(DB_CONN)和啟用的代理方法名(PROXY_FETCHER)。

啟動(dòng)項(xiàng)目

修改完配置之后,我們就可以愉快地使用了。

這個(gè)項(xiàng)目總體分為兩個(gè)部分:爬取代理 IP 和 取用代理 IP。

如果你要啟用爬取代理 IP 的服務(wù),直接運(yùn)行下面命令:

python proxyPool.py schedule

啟動(dòng)之后,你就可以看到如下的控制臺(tái)信息了:

爬蟲(chóng)福音:GitHub 超火爆開(kāi)源 IP 代理池

程序每隔一段時(shí)間就會(huì)定時(shí)爬取一下,直到我們的 IP 池里面有一定數(shù)量的可用 IP 。

其實(shí),作者在這個(gè)項(xiàng)目中運(yùn)用的原來(lái)就是到一些免費(fèi)的代理網(wǎng)站采集 IP,然后測(cè)試 IP 的可用性,可用的就存入 Redis 中,不可用就丟棄。

所以你完全可以自己寫一套程序?qū)崿F(xiàn)這個(gè)邏輯。

使用代理 IP

要使用代理 IP,你需要啟動(dòng) webApi 服務(wù):

python proxyPool.py server

啟動(dòng)web服務(wù)后, 默認(rèn)配置下會(huì)開(kāi)啟 http://127.0.0.1:5010 的api接口服務(wù):

爬蟲(chóng)福音:GitHub 超火爆開(kāi)源 IP 代理池

如果要在爬蟲(chóng)代碼中使用的話, 可以將此api封裝成函數(shù)直接使用,例如:

import requests def get_proxy(): return requests.get("http://127.0.0.1:5010/get/").json() def delete_proxy(proxy): requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy)) # your spider code def getHtml(): # .... retry_count = 5 proxy = get_proxy().get("proxy") while retry_count > 0: try:
            html = requests.get('http://www.example.com', proxies={"http": "http://{}".format(proxy)}) # 使用代理訪問(wèn) return html except Exception:
            retry_count -= 1 # 刪除代理池中代理 delete_proxy(proxy) return None 

總結(jié)

作為學(xué)習(xí)使用的 IP 代理池,這項(xiàng)目獲取的足夠使用了,但是對(duì)于一些復(fù)雜的爬蟲(chóng)項(xiàng)目或者商業(yè)項(xiàng)目的話,可能比較夠嗆,畢竟這種爬取的免費(fèi)代理質(zhì)量肯定沒(méi)有那么好,不穩(wěn)定是正常的。

數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼

若不方便掃碼,搜微信號(hào):CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機(jī)數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個(gè)參數(shù)驗(yàn)證碼對(duì)象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個(gè)配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺(tái)檢測(cè)極驗(yàn)服務(wù)器是否宕機(jī) new_captcha: data.new_captcha, // 用于宕機(jī)時(shí)表示是新驗(yàn)證碼的宕機(jī) product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說(shuō)明請(qǐng)參見(jiàn):http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計(jì)時(shí)完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請(qǐng)輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請(qǐng)輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }