python 爬蟲 入門 commit by commit -- commit1

"每一個commit都是程序員的心酸,哦不,心路歷程的最好展示。" -- by 我自己

最近寫好了一組文章,來這裏,當然一如我以前一樣,主要是宣傳。但是,最近發現gitbook老是掛掉,除了宣傳,我覺得,在這裏全部貼一遍,這樣就算是gitbook那邊不穩定,至少這裏還能看到。不過說實話,如果有興趣的話,我還是推薦去gitbook那邊看,因爲博客園的結構,貌似不適合這種系列型的文章。

目前所有完結版本都已經可以在https://rogerzhu.gitbooks.io/python-commit-by-commit/content/ 看到,因爲博客園一天只能貼一篇首頁的文章,所以我可能需要一點時間把所有的都貼完。當然,你可以去gitbook上看已經完結的。而代碼,我放在了https://github.com/rogerzhu/relwarcDJ ,裏面有我完整的commit記錄。有興趣的話可以盡情star。 而且我覺得這裏扯淡和準備篇的文字我就不貼了,有興趣可以從上面的gitbook地址看到。

廢話少說,搬運工作開始:

Commit1

"F12纔是爬蟲開發的最好的朋友" -- by 我自己

既然叫commit by commit,那就要按照自己給自己定下的規矩來寫。在把代碼clone到本地之後,你可以用git reset --hard 6fda96eae來退回到代碼的第一個版本。別擔心回不去後面的版本,這commit都在github都能看到,即使你不知道一些奇技淫巧的git命令也沒啥,大膽幹。

首先,我覺得我應該說這個commit我想幹嘛,第一個commit,我是想作爲熟悉的門檻,所以這個commit最開始我的本意是想獲得京東圖書編程語言第一頁上面的書名,鏈接。

對於這個commit,當你輸入如下命令開始運行時:

你應該能看到如下的結果:​

前面已經扯了兩篇了,那麼從這篇開始步入技術的正軌了,其實從骨子裏我是很討厭那種教程裏敲半個小時代碼,最後發現就是一個輸出了一個星號組成的圖案。我覺得,入門級別的代碼得用不超過10分鐘的時間幹出一點你能看得到,有成就感的正事才能吸引大部分的注意力。可惜啊,C++在這方面確實很難做到,而python在這方面絕對是擅長。所以,第一個commit雖然我的comment是ugly commit,但是絕對能幹活。

既然是入門級別的文章,那麼就從最基本的部分開始,當你瀏覽一個網頁的時候,實際上,你在瀏覽什麼?實際上你在瀏覽的是服務器傳回來的一系列文件,這一系列文件由瀏覽器解析,然後呈現給你。比如我想看看京東圖書編程語言下面的所有圖書,我只要用鼠標一點一點的點到我想要的地方就可以看到我需要的網頁。

​​

但是作爲一個程序員,GUI並算是一個高效的交互方式,一個簡單的例子,對於文本可以一目十行,GUI除非你眼睛傳感器異於常人或者大腦CPU比一般人要性能好,不然很難做到。對於爬蟲,他不會關心GUI,它的食物只有一種,各類帶格式的文件。所以,我們需要看到界面背後的源碼。市面上只要你能見到的瀏覽器,在右鍵菜單裏一定會有讓你看到源碼的菜單。但是,在現代網頁越來越豐富的情況下,一個頁面的源碼文件實在是太豐富了,按照我最開始的說法,我想找到書名和價格,咋辦?不能用ctrl+f吧,低效不是程序員的作爲。在這個時候,職業的本能應該驅使你去尋找工具。

開心的是,主流瀏覽器都帶有這種工具,而且獲取這一組工具的方法都是隻要簡單的按下F12就可以了,我敢保證,當你按下這個鍵的時候,你有一種打開了新世界的感覺。比如我用的火狐,按下F12之後在最左邊,你會看到這樣一個圖標:

點擊一下這個圖標再移到界面上,你會發現你可以以矩形的方式選擇頁面上的元素。根據人的本能,點擊一下,你會發現圖標下面的html會自動定義到選中的元素!這樣,拿到什麼信息,你只要負責選擇就好了,瀏覽器自帶的工具會自動幫你定位。比如,我想要的圖書的名字和價格,我選中某一格的圖書,就會看到這樣的輸出:

html是一種格式化並且是帶有層級的語言,這樣就會自然引申出一個問題,當我選取一個元素時候,到底採用怎樣的粒度?比如說,就以這個圖書的名字來說,他是在一個列表(li)元素中的一個div中的一個text中的,那麼完全可以直接選取這個text,第二個是通過父級別一點一點的選取。這其實就是一個數據結構大小取捨的問題,而寫程序,我覺得要考慮到擴展性和人思維的自然認知性,以便於升級和維護。所以,我一般都是從我自己最自然的認知出發,當我的眼睛看到這個網頁時,我的呆腦,哦不,是大腦會自然把每個圖的一個縮略圖,名稱和價格組成的這個方塊歸類爲一個小組,於是,我選擇的粒度就是遵從我的內心。

那麼我就用上面說的小箭頭選取到我決定的方塊,可以得到標識這每一方塊的元素是<li>。而在這個HTML中,有無數的li,我們怎麼能定位到我們需要的這個li呢?這裏,讓我不得不想起一個諺語,叫贈人玫瑰手有餘香。在前端程序員在開發他們的網頁時,他們需要對元素進行標識,這樣他們才能在代碼中方便的寫出想要的邏輯。而這個行爲,給爬蟲程序員們提供了便利,你可以用他們歸類的標識來定位你需要的元素,當然,我這裏說的是在代碼裏。而beautifulsoup這個包可以非常的方便的讓你完成這件事情,你可以選擇用id,class等等來找到你需要的元素。而在這裏,如果你按照我說的使用箭頭工具的話,會很容易的看到在這個網頁中gl-item這樣的class來標識每一個列表塊。那麼剩下的就是按照已經發現的,翻譯成爲程序語言了。

在第一個commit裏面,代碼一共22行,我都忍不住用截圖的方式展示一下以便於說明。

​​

這個代碼前7行都是shebang,coding的設置和import包。這裏你不知道shebang也一點也不影響你對於這一系列問斬的閱讀理解。所以說,正文從第九行看起就行了。

首先python提供了非常方便的方法獲取網頁的源碼,我以前最開始的時候使用C++寫過爬蟲,怎麼形容呢?如果python爬蟲的給力程度是他孃的意大利炮,那麼c++就是純物理攻擊了。你只需要使用urllib中的request.urlopen就能直接獲取到網頁源碼。而需要的參數僅僅是網頁的url。一如第九行所示。

當有了源碼之後,按照前面介紹的邏輯,就是尋找對應的元素了,而這個時候就是BeautifulSoup包上場的時候了,把得到的源碼字符串作爲參數傳給BeautifulSoup庫,你就會得到一個強大的方便解析的BeautifulSoup對象。而在BeautifulSoup中,使用findAll你就可以找到全部的帶有某種標識的某種元素。比如說,在我們要爬取的頁面上,有很多的書,而我們又知道每個書所存在的塊是以gl-item的class來標識的列表,那麼只要對findAll傳入元素名稱和標識規則就行了。而BeautifulSoup還提供一個find函數,用來找到第一個符合標識的對象。

既然已經得到需要的一大塊了,剩下的就是在這一大塊中找到自己想要的信息,比如我想要的書名和鏈接地址。其實這後面的過程就是前面描述的過程的重複。大致就是找到頁面->按下F12->使用選擇工具->找到對應的元素塊。但是程序員嘛,都很懶,能少動幾下鼠標是幾下,所以,如果一個塊中元素規模不大的並且基本都相像的情況下,我會使用這樣的一種辦法:把一大塊的html片段輸出到一個文件裏。如果你覺得我說的有點繞了,那麼其實我想表達的就是第12行語句的意思,雖然我這裏用的是print,但是你可以使用重定向的功能將這個輸出到一個文件中,也就是"> item.txt"類似的語句。而如果你查看這個commit的目錄結構,你就會看到這麼一個文件。如果好奇心仍驅使你打開它,那麼你就可以看到一個li中的所有內容。這樣就省去了前面那四個步驟的煩惱,而且你可以反覆查看,而不用反覆的打開瀏覽器。

當然,這是在我下面的循環還沒有寫出來的時候先輸出的。

談到這個while循環,在這裏你可以完全忽略,或者說你可能會揣測這到底有什麼深意。其實沒啥深意,就是爲了後面用的,而且還是比較後面的commit中才會用到。我只是有點懶,懶得刪除。實際上,這個程序的第15,16以及22行完全可以刪除,對於最後的結果完全沒有任何影響。

而這裏的for循環是肯定必要的。python的語法,按照其cookbook上說,已經非常接近自然語言了,從有的方面看真的是這樣的,比如說第17行,表示是依次取出allItem中的所有元素,對於每一個元素就是一個li塊,剩下的只要從這些li塊中再繼續尋找需要的信息就可以了。比如,書的標題實在class爲p-name的div元素之中。而在這個頁面上,真正的標題文字是放在強調標籤<em>之中。這都不能難住強大的BeautifulSoup庫,其對象可以像訪問結構中成員一般一層一層的找到需要的元素。如果想要獲得某個標籤中的文字,只需要使用get_text函數就可以獲得。用代碼說話的話就是18,19行。

而有的時候我們不是要獲取某個標籤中的元素,而是要獲取某個標籤中的屬性怎麼辦?BeautifulSoup用近乎完全符合自然思維的方式實現了這一點。比如超鏈接,一般都是在<a>標籤中href屬性之中,那麼href就是a這個成員(字典)的一個關鍵詞,通過這個關鍵詞,你就可以取得其中的值,一如你看到的href="xxx"一樣,典型的key,value結構。也就是程序的第20行,通過這樣的方式,就可以取得每個圖書的鏈接。

剩下來,就是你怎麼呈現這個數據的部分了,我這裏就簡單大方而又明瞭的輸出,keep it simple,stupid。

這裏,第一個commit就結束了,去掉不需要while循環,一共就19行代碼,在環境配好的情況下,無腦敲完不需要5分鐘,運行python myGAND.py,你就可以看到京東圖書編程語言第一頁的書名和鏈接打印在控制檯或者文件中。說實話,如果是C++,你可能還在寫各種字符串解析函數的過程中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章