抓取如果抓取的太快太頻繁會被源站封ip,本文會介紹下通過限流、限速和使用**的方式來防止被封上篇文章,抓取「電影天堂」最新的170部電影,在抓取首頁電影list之後,會同時發出170個請求抓取電影的詳情頁,這樣在固定時間點集中爆發式的訪問頁面,很容易在日誌中被找出來,而且併發請求大了,很可能會中**的防火牆之類的策略,ip被加到黑名單就悲劇了
這裡我使用async
模組限制併發次數,async
主要有:集合、流程和工具三大類方法,這裡我使用eachlimit(arr, limit, iterator, [callback])
,所有修改是上篇文章的fetchcontents
方法,該方法接受抓取到的170個文章的url list,這次通過eachlimit
將170個url按照3個一組併發,依次執行,具體**如下:
function
fetchcontents (urls) , ,
title:
}).then((d) => , () => )
}, () => )
})}複製**
限流只是控制了一次併發的請求數,並沒有讓抓取程式慢下來,所以還需要限速,在限流的基礎上限速就變得很簡單,只需要在執行eachlimit
的callback
的時候,加上個timer
就好了,為了方便檢視限速的效果,每次抓取成功之後,都console.log
顯示時間,所以改完的**如下:
function fetchcontents (urls) , ,
title:
}).then((d) => ===>success, $`)
results.push(d)
settimeout(callback, 2e3)
}, () => )
}, () => )
})}複製**
效果如下:
因為一些**更新比較慢,我們寫的抓取程式在定時指令碼任務(crontab)跑的時候,可能**還沒有更新,如果不做處理會造成資源的浪費,尤其國內不少vps都是有流量限制的,不做控制,真金**就打水漂了。。
繼續拿「電影天堂」最新更新的內容進行抓取,如果假設每五分鐘執行一次抓取指令碼,那麼需要記錄下已經抓取過的文章(電影),這裡我簡單處理一下,通過乙個_fetchedlist.json
的檔案,記錄抓取完的文章(電影)。具體思路如下:
抓取每個電影詳情頁成功後,將抓取到的url放入乙個陣列array
等全部抓取結束,將這個陣列array,寫到檔案_fetchedlist.json
下次抓取的時候,require這個_fetchedlist.json
,得到陣列array,抓取之前判斷要抓取的url是否在這個陣列內
陣列保持長度是300(170個電影夠用了),保證先入先出,即超過300長度將最早的移出
具體**講解如下:
引入抓取的記錄檔案
var fs = require('fs-extra')
var path = require('path')
var uniquearray =
const unique_array_url = './_fetchedlist.json'
try catch (e) 複製**
改造url處理函式,過濾下url陣列,已經抓取過的就不要抓取了function
deallistdata (data) ).filter(url => )
// 如果為空就reject
urls.length ? resolve(urls) : reject('empty urls')
} else
})}複製**
增加乙個處理方法,保持uniquearray
長度是300,不要無限增加function
adduniquearray (url)
}複製**
在抓取完之後,記錄新的uniquearray
陣列內容到json
檔案:fetchlist().then(deallistdata).then(fetchcontents).then((d) => ).catch((e) => )複製**
為了迷惑被抓取的**,除了偽裝user-agent等方法,最重要的是使用**服務,如果有錢的主可以買**,然後用,對於我們做demo,那就直接抓取**吧!下面**是抓取快****的****:
var spider = require('../lib/spider')
function
fetchproxy () , )
if (proxy[0] && proxy[1] && /\d.\d.\d.\d/.test(proxy[0]) && /\d/.test(proxy[1])) else
return proxy}})
}fetchproxy().then(data => )複製**
抓取之後的**不一定直接就可以用,還需要測試下**是否可以訪問成功我們要抓取的**,先寫個checkproxy(proxy)
的方法,用於檢測使用傳入的proxy是否抓取成功:
function
checkproxy (proxy) ,
})}複製**
fetchproxy().then(data => :$`).then(() => ).finally(done).catch(e =>
void (e))
})function
done ()
}})複製**
這裡最後console.log
出來的就是通過**抓取成功的**,可以存入到資料庫,以後抓取使用。
**的維護
最後在簡單說下**的維護,抓取到了**,因為是免費的,一般過一段時間就會不能用了,所以在使用的時候,可以將**放到乙個資料庫中維護,資料庫中有字段:succcount
和failcount
用於記錄每次使用該**成功和失敗的次數。每次使用**抓取的時候,要有個反饋機制,如果成功就succcount
+1 ,失敗就failcount
+1。當失敗次數過多的時候,這個**就不要再使用了。
本系列寫到第三篇了,後面還會有一些常見問題解答。週末看到一篇用python抓知乎匯出txt或者markdown的文章,以後手癢就會放出番外篇 ?
關注三水清
App防止被抓包
1.使用https,可以初步防止一些只抓http包的軟體。2.如果網路框架使用的是okhttp,可以在builder中設定proxy proxy.no proxy 屬性,禁止使用 這樣一般使用中間人的 就使用不了,客戶端是直接訪問伺服器。3.判斷是否使用了 final boolean flag bu...
移動端防止被抓包
最近在除錯乙個bug的時候沒有其它好的辦法了,用到了抓包這麼個方式才發現問題,不過問題已經解決了 不過在抓包的時候突然想到了,我擦,我用的https也可以被抓到包啊。所以又看了一下https的鏈結建立的流程 ssl tls原理詳解 和相關的中間人攻擊的流程,想了一下其中的原理。1.客戶端首先要向遠端...
AF 配置https證書,防止被抓包
1.afsecuritypolicy customsecuritypolicy 需要伺服器提供乙個crt檔案 把.crt檔案 匯入 鑰匙串中,並匯出.cer證書 把.cer證書 放在 專案目錄下,並作如下操作。把第一段 放在你 網路請求的類中。順便 加上 在網上查到的資料 afsecuritypol...