作者:xlzd
鏈接:https://zhuanlan.zhihu.com/p/20430122
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
好了,到上一篇博客,我們已經(jīng)能夠順利從網(wǎng)站上抓取一些簡單的數(shù)據(jù),并將其存儲到文件中。但是在抓取網(wǎng)頁的時候,有時候會發(fā)現(xiàn)HTML中沒有我們需要的數(shù)據(jù),這時候如何是好呢?
-------------------------------------
我們的目的是抓取拉勾網(wǎng)Python分類下全國到目前為止展示出來的所有招聘信息,首先在瀏覽器點擊進(jìn)去看看吧。如果你足夠小心或者網(wǎng)速比較慢,那么你會發(fā)現(xiàn),在點擊Python分類之后跳到的新頁面上,招聘信息出現(xiàn)時間是晚于頁面框架出現(xiàn)時間的。到這里,我們幾乎可以肯定,招聘信息并不在頁面HTML源碼中,我們可以通過按下"command+option+u"(在Windows和Linux上的快捷鍵是"ctrl+u")來查看網(wǎng)頁源碼,果然在源碼中沒有出現(xiàn)頁面展示的招聘信息。
到這一步,我看到的大多數(shù)教程都會教,使用什么什么庫,如何如何模擬瀏覽器環(huán)境,通過怎樣怎樣的方式完成網(wǎng)頁的渲染,然后得到里面的信息......永遠(yuǎn)記住,對于爬蟲程序,模擬瀏覽器往往是下下策,只有實在沒有辦法了,才去考慮模擬瀏覽器環(huán)境,因為那樣的內(nèi)存開銷實在是很大,而且效率非常低。
那么我們怎么處理呢?經(jīng)驗是,這樣的情況,大多是是瀏覽器會在請求和解析HTML之后,根據(jù)js的“指示”再發(fā)送一次請求,得到頁面展示的內(nèi)容,然后通過js渲染之后展示到界面。好消息是,這樣的請求往往得到的內(nèi)容是json格式的,所以我們非但不會加重爬蟲的任務(wù),反而可能會省去解析HTML的功夫。
那個,繼續(xù)打開Chrome的開發(fā)者工具,當(dāng)我們點擊“下一頁”之后,瀏覽器發(fā)送了如下請求:
注意觀察"positionAjax.json"這個請求,它的Type是"xhr",全稱叫做"XMLHttpRequest",XMLHttpRequest對象可以在不向服務(wù)器提交整個頁面的情況下,實現(xiàn)局部更新網(wǎng)頁。那么,現(xiàn)在它的可能性最大了,我們單擊它之后好好觀察觀察吧:
點擊之后我們在右下角發(fā)現(xiàn)了如上詳情,其中幾個tab的內(nèi)容表示:
Headers:請求和響應(yīng)的詳細(xì)信息
Preview:響應(yīng)體格式化之后的顯示
Response:響應(yīng)體原始內(nèi)容
Cookies:Cookies
Timing:時間開銷
通過對內(nèi)容的觀察,返回的確實是一個json字符串,內(nèi)容包括本頁每一個招聘信息,到這里至少我們已經(jīng)清楚了,確實不需要解析HTML就可以拿到拉鉤招聘的信息了。那么,請求該如何模擬呢?我們切換到Headers這一欄,留意三個地方:
上面的截圖展示了這次請求的請求方式、請求地址等信息。
上面的截圖展示了這次請求的請求頭,一般來講,其中我們需要關(guān)注的是Cookie / Host / Origin / Referer / User-Agent / X-Requested-With等參數(shù)。
上面這張截圖展示了這次請求的提交數(shù)據(jù),根據(jù)觀察,kd表示我們查詢的關(guān)鍵字,pn表示當(dāng)前頁碼。
那么,我們的爬蟲需要做的事情,就是按照頁碼不斷向這個接口發(fā)送請求,并解析其中的json內(nèi)容,將我們需要的值存儲下來就好了。這里有兩個問題:什么時候結(jié)束,以及如何的到j(luò)son中有價值的內(nèi)容。
我們回過頭重新觀察一下返回的json,格式化之后的層級關(guān)系如下:
很容易發(fā)現(xiàn),content下的hasNextPage即為是否存在下一頁,而content下的result是一個list,其中的每項則是一條招聘信息。在Python中,json字符串到對象的映射可以通過json這個庫完成:
importjsonjson_obj=json.loads("{'key': 'value'}")# 字符串到對象json_str=json.dumps(json_obj)# 對象到字符串
json字符串的"[ ]"映射到Python的類型是list,"{ }"映射到Python則是dict。到這里,分析過程已經(jīng)完全結(jié)束,可以愉快的寫代碼啦。具體代碼這里不再給出,希望你可以自己獨立完成,如果在編寫過程中存在問題,可以聯(lián)系我獲取幫助。
小結(jié)
這篇博客介紹了有些數(shù)據(jù)不在HTML源碼中的情況下的抓取方法,適用于一部分情況。對于數(shù)據(jù)的存儲暫時還是在使用文件。到下一篇,我們將使用MongoDB存儲數(shù)據(jù),所以在這之間,希望你可以先在本機(jī)安裝并配置好MongoDB。