天天看點

記python開發網絡爬蟲所遇問題

最近幾天一直在寫網絡爬蟲,用的是python,圖的是友善省事,不過中間确實遇到過幾次讓人頭疼的問題,現記錄如下:

一.建立網絡連結的問題

使用的是python提供的urllib2子產品,用urllib2.urlopen()函數建立連結,該函數抛錯率高,還可能不響應,是以要設定timeout,并使用try except else來容錯。

二.從連結中讀取資料的問題

使用urlopen獲得response後,調用respons.read()讀取網頁資料,這也是程式假死的罪魁禍首之一,更無奈的是該函數不接受timeout參數,導緻線程直接卡死在這兒,并且python不像ruby一樣直接支援函數的timeout寫法,是以這個問題很棘手,目前尚未解決。

今天看來可能不是read函數出問題,還是出在print上面。一個解決方法是主程式将需要爬的url清單分成若幹份,每次建立多線程去讀取其中一份并将資料記錄下來,如此依次解決掉所有的url。不算完美,但還是一個較容易實作的記錄中間結果的辦法。

三.多線程問題

爬資料當然要用到多線程,比如threading子產品,多線程最要注意的就是死鎖現象,但是在隻使用了一把鎖的情況下依然出現了,查了半天,發現極大可能是臨界區中的print函數造成的。按理說print應該是時間片占用,到時間了該自動釋放,但事實卻是它造成了死鎖(不算很嚴密的驗證過),将print從臨界區移除後死鎖現象消失了,但是為什麼會這樣不太了解。

今天又出現了數次類似現象,都是線程在做pinrt操作時,沒有完成,并且一直卡在那,并且還是在非臨界區。難道python的print和多線程真有沖突?如果是這樣隻有采用寫log檔案的方法了。

四. 編碼問題

從網頁上面爬下來的内容編碼常常特别混亂,即使網頁上的charset寫明是某種編碼,如'gb2312',也往往不太可靠,用python進行String的decode操作時常常出錯,尤其是要把其中部分内容放入資料庫時。

一種做法是采用decode函數的 'ignore' 參數,這樣可以忽略網頁上的小部分亂碼,避免一顆老鼠屎壞一鍋湯的問題。但是很可能做完parsing以後要把結果存入DB,這時這些内容很可能亂碼,即使你把内容輸出到螢幕時是正常的。針對這種情況,我的一個經驗是利用剪貼闆,比如你把結果都寫入到 result.txt 檔案,然後建立一個 true_result.txt 檔案,并且把 result.txt 檔案裡面的内容複制粘貼過來,通過這個過程,不規範的亂碼被去除了,剩下幹淨的編碼,然後存入Database。