如何開發高級Python爬蟲?

如何寫一個高質量的Python爬蟲,同時優化爬蟲性能和將爬取的內容高效率的存入MySQL資料庫?以及如何學習利用Python做搜索的功能


由於本學期好多神都選了Cisco網路課, 而我這等弱渣沒選, 去蹭了一節發現講的內容雖然我不懂但是還是無愛. 我想既然都本科就出來工作還是按照自己愛好來點技能吧, 於是我就不去了. 一個人在宿舍沒有點計劃好的事情做就會很容易虛度, 正好這個學期主打網路與資料庫開發, 那就先學學Python開發爬蟲吧. 我失散多年的好朋友Jay Loong突然說他會爬蟲了, 我感到真棒, 我也要學 :D 因為一個星期有兩節Cisco課, 所以本系列博文也就一周兩更。

選擇一門語言

爬蟲可以用各種語言寫, C++, Java都可以, 為什麼要Python? 首先用C++搞網路開發的例子不多(可能是我見得太少), 然後由於Oracle收購了Sun, Java目前雖然在Android開發上很重要, 但是如果Google官司進展不順利, 那麼很有可能用Go語言替代掉Java來做Android開發. 在這計算機速度高速增長的年代裡, 選語言都要看他爹的業績, 真是稍不注意就落後於時代. 隨著計算機速度的高速發展, 某種語言開發的軟體運行的時間複雜度的常數係數已經不像以前那麼重要, 我們可以越來越偏愛為程序員打造的而不是為計算機打造的語言. 比如Ruby這種傳說中的純種而又飄逸的的OOP語言, 或者Python這種稍嚴謹而流行庫又非常多的語言, 都大大弱化了針對計算機運行速度而打造的特性, 強化了為程序員容易思考而打造的特性. 所以我選擇Python。

選擇Python版本

有2和3兩個版本, 3比較新, 聽說改動大. 根據我在知乎上搜集的觀點來看, 我還是傾向於使用」在趨勢中將會越來越火」的版本, 而非」目前已經很穩定而且很成熟」的版本. 這是個人喜好, 而且預測不一定準確. 但是如果Python3無法像Python2那麼火, 那麼整個Python語言就不可避免的隨著時間的推移越來越落後, 因此我想其實選哪個的最壞風險都一樣, 但是最好回報卻是Python3的大. 其實兩者區別也可以說大也可以說不大, 最終都不是什麼大問題. 我選擇的是Python 3。

選擇參考資料

由於我是一邊學一邊寫, 而不是我完全學會了之後才開始很有條理的寫, 所以參考資料就很重要(本來應該是個人開發經驗很重要, 但我是零基礎).

  • Python官方文檔
  • 知乎相關資料(1) 這篇非常好, 通俗易懂的總覽整個Python學習框架.
  • 知乎相關資料(2)

寫到這裡的時候, 上面第二第三個鏈接的票數第一的回答已經看完了, 他們提到的有些部分(比如爬行的路線不能有迴路)我就不寫了.

一個簡單的偽代碼

以下這個簡單的偽代碼用到了set和queue這兩種經典的數據結構, 集與隊列. 集的作用是記錄那些已經訪問過的頁面, 隊列的作用是進行廣度優先搜索.

Python1234567891011queue Qset SStartPoint = "http://jecvay.com"Q.push(StartPoint) # 經典的BFS開頭S.insert(StartPoint) # 訪問一個頁面之前先標記他為已訪問while (Q.empty() == false) # BFS循環體 T = Q.top() # 並且pop for point in PageUrl(T) # PageUrl(T)是指頁面T中所有url的集合, point是這個集合中的一個元素. if (point not in S) Q.push(point) S.insert(point)

這個偽代碼不能執行, 我覺得我寫的有的不倫不類, 不類Python也不類C++.. 但是我相信看懂是沒問題的, 這就是個最簡單的BFS結構. 我是看了知乎裡面的那個偽代碼之後, 自己用我的風格寫了一遍. 你也需要用你的風格寫一遍.

這裡用到的Set其內部原理是採用了Hash表, 傳統的Hash對爬蟲來說佔用空間太大, 因此有一種叫做Bloom Filter的數據結構更適合用在這裡替代Hash版本的set. 我打算以後再看這個數據結構怎麼使用, 現在先跳過, 因為對於零基礎的我來說, 這不是重點.

代碼實現(一): 用Python抓取指定頁面

我使用的編輯器是Idle, 安裝好Python3後這個編輯器也安裝好了, 小巧輕便, 按一個F5就能運行並顯示結果. 代碼如下:

Python1234567#encoding:UTF-8import urllib.request url = "http://www.baidu.com"data = urllib.request.urlopen(url).read()data = data.decode("UTF-8")print(data)

urllib.request是一個庫, 隸屬urllib. 點此打開官方相關文檔. 官方文檔應該怎麼使用呢? 首先點剛剛提到的這個鏈接進去的頁面有urllib的幾個子庫, 我們暫時用到了request, 所以我們先看urllib.request部分. 首先看到的是一句話介紹這個庫是幹什麼用的:

The urllib.request module defines functions and classes which help in opening URLs (mostly HTTP) in a complex world — basic and digest authentication, redirections, cookies and more.

然後把我們代碼中用到的urlopen()函數部分閱讀完.

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False)

重點部分是返回值, 這個函數返回一個 http.client.HTTPResponse 對象, 這個對象又有各種方法, 比如我們用到的read()方法, 這些方法都可以根據官方文檔的鏈接鏈過去. 根據官方文檔所寫, 我用控制台運行完畢上面這個程序後, 又繼續運行如下代碼, 以更熟悉這些亂七八糟的方法是幹什麼的.

Python123456789101112&>&>&> a = urllib.request.urlopen(full_url)&>&>&> type(a)& 『http.client.HTTPResponse』&> &>&>&> a.geturl()『http://www.baidu.com/s?word=Jecvay』 &>&>&> http://a.info()& at 0x03272250&> &>&>&> a.getcode()200

代碼實現(二): 用Python簡單處理URL

如果要抓取百度上面搜索關鍵詞為Jecvay Notes的網頁, 則代碼如下

Python12345678910111213import urllibimport urllib.request data={}data["word"]="Jecvay Notes" url_values=urllib.parse.urlencode(data)url="http://www.baidu.com/s?"full_url=url+url_values data=urllib.request.urlopen(full_url).read()data=data.decode("UTF-8")print(data)

data是一個字典, 然後通過urllib.parse.urlencode()來將data轉換為 『word=Jecvay+Notes』的字元串, 最後和url合併為full_url, 其餘和上面那個最簡單的例子相同. 關於urlencode(), 同樣通過官方文檔學習一下他是幹什麼的. 通過查看

  1. urllib.parse.urlencode(query, doseq=False, safe=」, encoding=None, errors=None)
  2. urllib.parse.quote_plus(string, safe=」, encoding=None, errors=None)

大概知道他是把一個通俗的字元串, 轉化為url格式的字元串.

最後:我有建立一個python學習交流群,在群里大家相互幫助,相互關心。相互分享知識,多一個人多一個想法,只有人多的時候遇到問題才會有更多的人幫你解決問題,如果你也是願意分享,不是單純的伸手黨我歡迎你來群里,先在搜索框裡面加483在加上546 最後是416 這樣你就可以找到組織大家一起來分享

快速學習python交流總群:619307290 &>48354641


在對HTTP和WEB足夠了解的基礎上,本質上回到了數據結構+演算法的問題,語言的選擇這裡其實是其次的了(只是有方便與否之分)。


推薦閱讀:

python多線程爬蟲設計?
學習爬蟲應該從哪裡學起?
如何用八爪魚採集器提取新浪微博的數據呢?
如何利用python asyncio編寫非同步爬蟲?
python抓取網易財經的個股的財務數據,比如利潤表,並分項保存到mysql,需要哪些步驟?

TAG:學習 | Python | MySQL | 爬蟲計算機網路 | Python開發 |