2018年10月30日 星期二

R語言-迴圈爬網被鎖定(連線被拒絕)解決方式

部分網站對於爬蟲會設有每幾秒鐘不得超過幾次之類的設定,如果網站很單純的只是為了防堵被暴力存取,一般就是使用"延遲"指令來解決。

在R語言中
Sys.sleep(x)代表延遲x秒,儘可能模擬為人正常存取的秒數
Sys.sleep(runif(1,3,5)) 以亂數產生3~5秒鐘的值來延遲(太規律有人說不好,容易被篩選鎖定)。

上面這種狀況很單純,只要延遲合理的秒數,挖掘資料就不成問題。

某網站很特別,我覺得我的秒數已調得很人性化還是把我黑掉(總不能抓20次,延遲30分鐘吧),檢討原因可能是除了基本的 [每幾秒鐘不得超過幾次]的設定外,還有做額外的限制,例如不能長時間存取。

為了解決連線被拒絕情形,我嘗試在迴圈程式碼裡面試過每10次或20次或更多次抓取時就額外增加延遲幾秒,結果最終還是失敗,也讓我放棄單純的以延遲的方式去爬網了。

變通方式:"延遲"+"重新連線"
我的作業環境:win10+中華電信寬頻(非DHCP)

以下直接以程式碼說明:

    # 前面亂數等待時間,還是無法應付網站踢人的邏輯(連線被拒絕),所以補上
    # try(getURLContent(url1))    if(inherits(webdata, "try-error")){} 邏輯,
    #自動斷網及連網,並重新從斷點的j值再次跑迴圈
    webdata<-try(getURLContent(url1))
    if(inherits(webdata, "try-error")){
      x<-j #將斷點的j值保存起來
      shell("z:/hinet-unconnect.cmd") #shell():執行DOS指令-網路中斷連線,檔案放在Z槽
      Sys.sleep(runif(1,6,10))
      shell("z:/hinet-connect.cmd") #shell():執行DOS指令-寬頻重新撥接,檔案放在Z槽
      Sys.sleep(runif(1,6,10))
      next #假如中斷情形發生,下面的code就跳過不執行,帶著x值跳回j迴圈開始處重新跑迴圈
    }

補充說明二個CMD檔-中華電信寬頻(非DHCP)的離線及連線(取得新的 ip)
1.hinet-connect.cmd
   rasdial 你的寬頻連線名稱 你的帳號  你的密碼
2.hinet-unconnect.cmd
   rasdial 你的寬頻連線名稱 /DISCONNECT

當連線被拒絕情形發生時,透過 try捕捉到錯誤訊息然後執行斷網重新連線取得新 ip ,就可以從斷線時的 j 值接續下去爬網,而不會被迫中斷,直到整個迴圈結束。