python 爬蟲 入門 commit by commit -- commit2
"每一個commit都是程式員的心酸,哦不,心路歷程的最好展示。" -- by 我自己
最近寫好了一組文章,來這裡,當然一如我以前一樣,主要是宣傳。但是,最近發現gitbook老是掛掉,除了宣傳,我覺得,在這裡全部貼一遍,這樣就算是gitbook那邊不穩定,至少這裡還能看到。不過說實話,如果有興趣的話,我還是推薦去gitbook那邊看,因為部落格園的結構,貌似不適合這種系列型的文章。
目前所有完結版本都已經可以在https://rogerzhu.gitbooks.io/python-commit-by-commit/content/ 看到,因為部落格園一天只能貼一篇首頁的文章,所以我可能需要一點時間把所有的都貼完。當然,你可以去gitbook上看已經完結的。而程式碼,我放在了 ofollow,noindex">https://github.com/rogerzhu/relwarcDJ ,裡面有我完整的commit記錄。有興趣的話可以盡情star。 而且我覺得這裡扯淡和準備篇的文字我就不貼了,有興趣可以從上面的gitbook地址看到。
廢話少說,搬運工作開始:
“程式設計師是最不會偽裝但是又是最會偽裝的群體”--by 我自己
在運行了第一個commit的程式我估計也就三分鐘之內,你會覺得索然無味。圖書的標題和連結到底有什麼用呢?當然,我也有同樣的疑問,所以,我決定在第二個commit中爬取這個首頁我覺得我最關心的資訊,那就是錢——圖書的價格。
對於這個commit,當你輸入如下命令開始執行時:
你應該能看到如下的結果:
有了第一個commit中的三板斧,我感覺我已經信心與感覺並存,動力與技術齊飛了。於是我熟練的使用了選取工具,選到了價格的方框。火狐的工具給我顯示了,價格是在class名為p-price的div之內的。照葫蘆畫瓢一般的,使用BeautifulSoup的find,直接找到每個li中的這個div,熟練的儲存好檔案,開始用python執行。現實狠狠的給我了一個耳光,無論我怎麼輸出,這個價格都是拿不到的。
為什麼?我對著螢幕思考了3分鐘,畢竟如果思考再長的時間的話那隻能說明我的拖延症犯了。我重新回到我需要的頁面上,重新整理了下頁面,會看到價格資訊會比其他的資訊後出來,我又試了幾次,這不是偶然,每次都不是同時出來的。這個時候憑藉著我對web程式設計的一點粗淺的瞭解,我已經知道了,至少價格這個資訊不是和html資訊一起返回的。用在任何軟體語言裡都有的概念,這裡一點存在有回撥——callback。其實我在初學c++的時候對於這個概念不是很理解,但是如果你是第一次聽到這個概念,在這裡就特別形象,在某一件事情做完之後,又回頭呼叫了一個什麼介面或者檔案等等來取得結果。
到了這一步,就需要一點大膽猜測小心求證的哲學了,當然,還有得知道一點webapi的基本概念。其實簡單的說,就是呼叫一個url來獲得返回的結果,這個url中可以使用&傳入引數,而結果是一個檔案的方式傳到客戶端。而繼續前面所說的贈人玫瑰,手有餘香的邏輯,你要爬取的這個網站的程式設計師們也要考慮維護問題,加上業界對於某些反覆會出現的東西一定會有一套約定俗成的模式。說了這麼多,到底想表達什麼?既然我說webapi一般都是以檔案的方式返回結果,那麼怎麼看到這些從伺服器返回的檔案呢?很完美的事,這件事,又可以使用F12來解決。
當你按下F12的時候會有很多tab,其中有一個叫network,這個下面會記錄客戶端與伺服器端互動的所有內容。
Line"/>
既然是所有,那麼確實有點多,而且在大多數情況下,他會在不停的滾動,讓人很難操作。
這個時候只要你稍微網上看一點,就會發現,這些工具一定都會帶有搜尋功能的,畢竟,任何沒有搜尋功能的列表都是耍流氓。那麼這個時候就到了大膽發揮猜想的時候了,按照我前面的說的,寫程式的人為了維護一定會有某種比較共通的模式,既然價格是靠回撥取出來的,那麼不妨試試callback作為關鍵詞?或者這個是價格,用price作為關鍵詞?我選擇用callback,沒啥原因,只是因為我腦海裡第一反應是想用這個。於是我得到如下的結果,但是很明顯,一個網站上不可能只有一個callback。
但是這已經少多了,最差的結果一個一個暴力尋找,找什麼呢?找返回值,也就是右邊有的response的tab,找什麼返回值?因為每個callback當然都有返回值。當然找價格的數字了,既然你都能看到價格是多少錢,那麼response中含有這個價格當然就是你需要的webapi的地址啦。而很明顯,所有的callback返回的都是json字串,如果你實在沒有聽過json,也沒有關係,最簡單的你可以把他理解成是一個帶有格式的文字,這個文字的格式就是以逗號隔開的key,value字串。於是我就這樣暴力尋找,還真知道一個respons裡面帶有p:正確價格的字串。這個時候可以再回頭自己驗證一下,怎麼驗證?我的方法就是看看這個請求的url,驗證的方法還是本著良心程式設計師一定會把介面設計的另外一個程式設計師一看就懂的模式,吹的大一點,程式碼即文件。如果你看下這個請求的url,很明顯,有個關鍵詞告訴你,啊!這就是你要找的,那就是price,你可以在request URL中看到。你還可以再大膽的進一步,在這條記錄上右鍵,所有的F12工具都有copy url的功能,拷貝下這個地址,放在瀏覽器上,回車,你會發現,你可以看到一條返回的json字串。
仔細看看這些分會的字串,雖然都是縮寫,但是大概都能猜到是什麼意思,比如p後面是價格,id後面是標識,至於op和m的意思,我猜是什麼會員價和原價?不過沒關係,這裡面已經有了我們想要的資訊了。那麼想拿到價格的方法也很簡單了,按照前面了的路子,只要訪問這個網址然後拿到輸出傳給BeautifulSoup物件,就能完成解析了。但是,我們目前的想法是以一個書目,也就是一個list為一個Item,這個json字串似乎一次性傳回了很多個條目的價格。當然,可以通過字串處理然後選取合適的容器來取出每個圖書Item的價格。但這和我們的程式設計邏輯不搭,這東西就和寫文章一樣,行文邏輯不一致,會讓讀的人感到非常困難。放到程式碼上就是難以維護,那麼,有什麼辦法可以一條一條的取出價格就好了。
這個時候,不妨回頭看看獲取到這個json返回值的url,因為webapi,引數就在url上,真正的謎底就在謎面上。你想想,我們想獲取一個條目的價格,那麼如果你寫程式,一定是把這個條目的標識傳進去,然後獲取到價格。而我們現在使用的這個url有點長。