1. 程式人生 > >剛入門Python的同學看好了,這是騰訊大牛工作中總結的爬蟲經驗!

剛入門Python的同學看好了,這是騰訊大牛工作中總結的爬蟲經驗!

今天主要是說說工作中遇到的:

1.各類反爬蟲

2.一些小技巧

3.我自己常用的爬蟲框架

4.分享搭建一個簡單的代理池

好了,進入正題。

進群進群:943752371可以獲取Python各類入門學習資料!

這是我的微信公眾號【Python程式設計之家】各位大佬用空可以關注下,每天更新Python學習方法,感謝!

111111111111.png

 

剛入門Python的同學看好了,這是騰訊大牛工作中總結的爬蟲經驗!

首先是各類反爬蟲和小技巧,我穿插著講,好的,容我想想列一個表。

1.剛開始寫指令碼的時候經常忘記帶 request headers,特別是host和user-agent這倆個欄位(通常帶這兩個就足夠了),這個就是體現在對http協議理解不夠。具體是哪個網站我忘了,我因為沒有帶上ua,一直拿不到html,耽擱我不少的時間。

因為網站會檢查你的 request headers 中的host,如果不對,好的你拿不到資料,然後是檢測你的ua,嗯?什麼是ua,就是User-Agent,不同的瀏覽器有不同的ua,也是爬蟲偽裝瀏覽器的第一步。

2.關於cookies,這個我就遇到過一次,也是我上一份工作中遇到的,我要拿資料的那個網站,分析了url,確定了引數,post過去,嗯?怎麼是空網頁,資料喃。

這裡我們在用瀏覽器的開發者工具時,在network裡要關注所出現的各種url。後來我注意到在每次post後還有一個url緊跟著請求,原來這個post請求資料是個障眼法。

所以呢,這個就是網站通過post請求把引數放到cookies裡,然後到了真正出資料的url裡,在請求時帶上剛剛的cookies,伺服器在讀取完cookies接著就能看到資料了。

3.接下來就是ip的訪問頻率了。

我在入職現在這份工作時,老大讓我在xx網抓一份全國的旅行社資料,結果我的ip被ban,整個公司那一週都不能上那網站。所以,當我給老大彙報這個事情的時候,老大淡淡說了句,你當人家網站的運維chishi的麼。

同時,在這裡作為一名爬蟲工程師,基本的職業素養就包括,好比隔壁組坐著一個漂亮的菇涼,咱們看看就好了,不要去影響人家。所以說,在每兩次請求間一定要有時延。這裡我不是說,咱們通過測試來摸索出該網站的rps(request per second),然後就著rps來跑,這樣的確算是提高效率的方法,但是我偷懶,統一設定為10秒的時延。

但是,處理辦法有好幾種。

一,每一次請求時變更ua,就可以理解為學校機房裡,大家同時訪問一個url,難不成就把這個機房的ip給ban了?

二,在request headers裡帶上 referer,既然是模擬人的操作,那就在每一次請求的headers的referer裡帶上上一次的請求url。什麼?referer是做什麼的,這個就是告訴伺服器我是從哪一個url來到哪一個url去。

三, 設定時延,這個不解釋,我們抓資料的同時不能給伺服器造成太大壓力,也不能影響別人的瀏覽體驗。

四,使用代理, 通過改變代理ip的方式,讓伺服器沒辦法來阻止你拿資料。

4. 放在js中的反爬蟲,這裡我很願意來舉一個實際的栗子。客官們可以跟著我一起來看看人家怎麼反爬蟲的。

就說攜程酒店的評論資料好了。

http://link.zhihu.com/?target=http%3A//hotels.ctrip.com/

然後隨便點一個酒店進去,“shift+ctrl+i” 開啟開發者工具

然後拖動頁面去找評論,點選 更多評論, 這時候注意開發者工具裡的network裡的變化。

然後能看到這兩個

剛入門Python的同學看好了,這是騰訊大牛工作中總結的爬蟲經驗!

可以看到,我畫圈的就是關鍵,而下面那個AjaxHotelComment。是請求評論的頁面,因為在請求這個ajax時裡面有個引數eleven,看似是個token,實際不符合token的定義,總之就是在這個ajax請求前通過oceanball?這個請求得到一個eleven引數,然後交給請求ajax得到資料。

現在我們點進去那個畫圈的url,複製開一個新視窗開啟。

整理後的程式碼長這個樣子

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">eval(function(arr, f) {
if (typeof Array.prototype.map === "function") {
return arr.map(f)
}
var res = [],
j = 0;
for (var i = 0,
l = arr.length; i < l; i++) {
res[j++] = f(arr[i], i, arr)
}
return res
} ([.....],
function(item) {
return String.fromCharCode(item - 38644)
</pre>

eval這個臭名昭著效率低的東西恰巧就是反爬蟲利器,我們可以看到這段程式碼實際起作用的內容就是

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">arr.map(f)
</pre>

好的,我們來模擬。

我們開啟開發者工具的console,

在裡面輸入

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">var a = [那一大段的列表].map(function(item) {
return String.fromCharCode(item - 38644)
}).join('')
a //輸出結果
</pre>

結果就可以看到這樣的

剛入門Python的同學看好了,這是騰訊大牛工作中總結的爬蟲經驗!

也就是說,解碼後,給了這麼一段,(事實上這個跟網站底層的js有關聯,不然在底層的js裡找到 getElevenCode()這個function死活模擬不出來結果)。

好的,在站長工具裡對解析出來的這段js程式碼進行格式化,看到的結果呢,只想罵馬萌萌!!各個引數都是機器生成的。其中繞來繞去,被繞暈。

然後看到一段註釋,心想,嘿,後門吧。轉碼過來看,結果如下

剛入門Python的同學看好了,這是騰訊大牛工作中總結的爬蟲經驗!

剛入門Python的同學看好了,這是騰訊大牛工作中總結的爬蟲經驗!

好的呀!結果我被嘲諷了!再一次馬萌萌!!攜程的人太驕傲了。

從這裡我們數數人家的加密就有(1.請求得eleven 2.轉碼獲取新的js 3.再解碼)3層加密。

轉過來一想,都被嘲諷了,說明我離真相就近了。

那我們換一個思路,從底層js去找。

這時候我們去看人家從哪個js來

剛入門Python的同學看好了,這是騰訊大牛工作中總結的爬蟲經驗!

然後點進去,“ctrl+f”搜 ‘eleven’,結果我們找到這個

剛入門Python的同學看好了,這是騰訊大牛工作中總結的爬蟲經驗!

可是我沒看明白邏輯!!!!!!

於是我就卡在這了。

所以,攜程的這個栗子的反爬蟲就是通過噁心的js來完成。

為啥要這樣做,因為這類網站的資料不需要通過登陸就能看到

5. 然後就是驗證碼咯

老大通過機器學習訓練出可以識別xx網的驗證碼,已經上線了,所以驗證碼形同虛設(暫時的)

不過驗證碼依舊是我認為反爬蟲強有力的手段,因為涉及的技術很多,學習成本很高,很容易就放棄了。

6. 至於像淘寶啊 京東啊微博啊的種種反爬蟲,我還沒抓過,所以我也不清楚。

等等,被老大叫出去抽根菸 -.-!

好了,我回來了,剛剛跟老大聊了聊後面的工作安排。原本今天還打算寫一下框架和一個簡單的代理池,放後面好了, 不好意思哈 各位。

接下來我的工作就是弄爬蟲框架,還有分散式,所以我學到了什麼再來分享。