簡單爬蟲,突破IP訪問限制和複雜驗證碼,小總結

憤怒的TryCatch發表於2015-12-01
簡單爬蟲,突破複雜驗證碼和IP訪問限制

         文章地址:http://www.cnblogs.com/likeli/p/4730709.html

     好吧,看題目就知道我是要寫一個爬蟲,這個爬蟲的目標網站有一些反爬取意識,所以就有了本文了。

         我先說說場景吧:

         由於工作需要,平時有一大堆資料需要在網上查詢,並歸檔存庫。某次,這種任務也給我安排了一份。觀察了一網站,我的第一反應就是用爬蟲取抓取。這種機械的工作何必人工呢?

         由於這家網站有反爬蟲的意識,做了些工作,給我的爬蟲去爬取資料造成了某些麻煩。

先列舉出問題所在:

  •  首當其衝,驗證碼,該網站採用了數字加中文的簡單四則運算作為驗證碼。
  •  查詢目標路徑引數經過了加密,我並不能直接通過取路徑加引數的方式來直接跳過某些頁面。
  •  IP限制,該網站對訪問的IP做了訪問次數計數限制。經過我的測試,一個純淨IP訪問該網站一小時內最多能爬取40個有效資料(這裡針對我的抓取目標來說,HTTP請求次數差不多之多200次,但是若在30s內訪問次數超過25次HTTP請求,那麼這個IP就直接被封掉)

         好吧,主要的問題就是這些,一些爬取過程中的小問題,就不列舉了。園子裡面一大堆的解決方案。這裡我主要說的是,驗證碼和IP限制 的問題。

         當然,我的解決方案並不是什麼高超的技巧。應該都是老路子了。

1、  驗證碼

原圖:

  

         這種的驗證碼難度在於字元粘連,字元隨機旋轉問題。這兩種,我分別採用了投影直方圖分割卡殼法來分別切割字元和校正角度。

   我首先寫了一個工具來測試:

 

 

   從上面的效果圖,各位看官應該能看出,我的方法還是比較簡單和傳統的,那就是做特徵庫,通過分割出來的字元去匹配特徵庫的相似度來判斷圖片中的文字到底是什麼。這裡沒有使用 第三方的光學識別(OCR ),因為識別漢字感覺識別率還是比較差,而且驗證碼中的漢字其實並不多,就是幾個特定的字元,加減乘除等。所以通過特徵庫來識別也是綽綽有餘了。

    關於驗證碼,我來說說我的一些問題,對於灰度計算和二值化,園子裡面有很多演算法,但是對於降噪,也就是去干擾線,需要自己根據目標來寫特定的演算法。我這裡是通過削皮的方式來去掉的,每次給所有陰影剝掉一層1px的範圍,填充為白色。當然了,我這方法不具備通用性。不同的驗證碼需要根據觀察來用不同的方式來去除。

  分割呢,也就是直方圖了,其實我的驗證碼也是可以根據色彩來做單色的直方圖,這樣來一步完成分割字元和降噪(有這想法,但是沒有實際去實現。不過看有些大牛的部落格說這樣的方法是可行的)。我所瞭解到的分割方法還有滴水分割,不過我拿了論文資料,可惜看得不是很懂。下面貼了一段簡單繪製直方圖的方法:

 1 //繪製直方圖
 2 var zftbit = new Bitmap(bit4.Width, bit4.Height);
 3 using (Graphics g = Graphics.FromImage(zftbit))
 4 {
 5     Pen pen = new Pen(Color.Blue);
 6     for (int i = 0; i < bit4.Width; i++)
 7     {
 8         g.DrawLine(pen, i, bit4.Height - YZhiFang[i] * 2, i, bit4.Height);
 9     }
10     //閥值
11     g.DrawLine(new Pen(Color.Red), 0, bit4.Height - 2, bit4.Width, bit4.Height - 2);
12 }
13 p_zft.Image = zftbit;
繪製直方圖

  關於隨機旋轉的字元問題,我的做法是,將驗證碼中的字元分割成獨立單位後,進行正負30度旋轉,每旋轉一次,計算一次投影寬度,由於我們的字型基本上都是‘方塊字’,所以呢,在旋轉的時候,最小寬度肯定是‘擺正’了的,不過,這裡有個小問題,那就是若源字元旋轉超過45°,我們將字橫著放置的時候,其寬度也是最小的。不過我們讓機器多學習幾次,將四個方向擺放的圖形都學習了,就可以了。這就是卡殼法了。

2、IP限制問題

  這裡我用了最無賴也是最無解的方法來解決的。我直接通過切換訪問的代理來突破,這裡沒有絲毫技術性含量。掛上代理後,去訪問目標網站,根據返回的結果判斷代理是否還有效。若是無效了,將當前查詢目標回滾一次,並切換代理就行了。

3、爬蟲

  主角爬蟲來了,我最早設計的爬蟲是不控制時間的連續訪問的,這導致代理消耗的特別快。所以不得不想辦法解決這個問題。另外由於沒有專門的爬蟲伺服器,我只能通過辦公室的電腦來完成這項任務。由此,我設計了一個匯流排式爬蟲。

  我寫了一個爬蟲服務端和一個爬蟲客戶端,服務端當做中央處理器,來分配計算量,客戶端爬蟲用來抓取資料。這樣的情況下,各個客戶端執行的速度其實是不一樣的,請求響應又快又慢,驗證代理是否有效也需要時間,所有,客戶端爬蟲完成任務的時間肯定不一樣,所以我安排了這樣一臺電腦做作為中央處理器,分批次,小劑量的去分發任務列表。並接收客戶端回傳的結果,等完成所有任務之後統一匯出或者進行寫入資料庫等其他操作。

爬蟲節點

  每個節點上的爬蟲,給17個執行緒去跑,10個做代理IP的驗證,7個爬資料。若是給10臺辦公室的筆記本安裝軟體,一起去爬資料,那麼,就相當於 70人/秒 的速度在訪問這個網站。至此,效率問題也解決了。

匯流排

  匯流排方面,將任務列表根據下面的節點數進行分配(上圖是之前截的圖,之前是均分出去,後來發現均分的客戶端並不是同時完成,有的快有的慢,結果快的弄完了,就空閒了,慢的還在慢吞吞的跑,所以,之後進行了小劑量分配,變相的達到動態的安排任務量)。

後記

  文章到此就基本上結束了,程式碼不多,我主要數我的製作思路,因為我的的這個並不具備通用性,驗證碼家家基本都不一樣(一些極度簡單的規規矩矩的純數字或字母驗證碼不算,這類驗證碼跟沒有一樣)。

相關文章