手把手教你寫網絡爬蟲(5)html
做者:拓海 (https://github.com/tuohai666)git
摘要:從零開始寫爬蟲,初學者的速成指南!github
封面:web
你們好!從今天開始,我要與你們一塊兒打造一個屬於咱們本身的分佈式爬蟲平臺,同時也會對涉及到的技術進行詳細介紹。你們若是有什麼好的想法請多留言,多提意見,一塊兒來完善咱們的爬蟲平臺。在正式介紹平臺以前,先用一些篇幅對基礎篇作一點補充。數據庫
此次的目標是爬一個衆籌網站的全部項目,項目列表頁以下:https://www.kaistart.com/project/more.html。打開後進行分析,頁面顯示出10個項目:api
若是想看到更多項目,並不能像網易雲音樂那樣點「下一頁」翻頁,而是須要向下拉滾動條或者向下滾動鼠標滾輪來觸發異步請求。爬蟲該如何應對這種狀況呢?咱們可使用selenium的api執行js代碼將屏幕內容滾動到指定位置。瀏覽器
下面這段代碼會一直向下滾動項目頁,一直到滾不動爲止:服務器
# 一直滾動到最底部 js1 = 'return document.body.scrollHeight' js2 = 'window.scrollTo(0, document.body.scrollHeight)' old_scroll_height = 0 while browser.execute_script(js1) >= old_scroll_height: old_scroll_height = browser.execute_script(js1) browser.execute_script(js2) time.sleep(1)
scrollTo() 方法可把內容滾動到指定的座標:網絡
參數架構 |
描述 |
xpos |
必需。要在窗口文檔顯示區左上角顯示的文檔的 x 座標。 |
ypos |
必需。要在窗口文檔顯示區左上角顯示的文檔的 y 座標。 |
這裏用到了scrollHeight,它和ClientHeight還有OffsetHeight有什麼區別呢?
offsetHeight: 包括內容可見部分的高度,border,可見的padding,水平方向的scrollbar(若是存在);不包括margin。
clientHeight: 包括內容可見部分的高度,可見的padding;不包括border,水平方向的scrollbar,margin。
scrollHeight: 包括內容的高度(可見與不可見),padding(可見與不可見);不包括border,margin。
代碼寫好了,接下來就用selenium+phantomJs大法實驗一下!滾到底後把項目列表提取出來看一下:
browser = webdriver.PhantomJs() url = 'https://www.kaistart.com/project/more.html' try: browser.get(url) wait = ui.WebDriverWait(browser, 20) wait.until(lambda dr: dr.find_element_by_class_name('project-detail').is_displayed()) # 一直滾動到最底部 js1 = 'return document.body.scrollHeight' js2 = 'window.scrollTo(0, document.body.scrollHeight)' old_scroll_height = 0 while browser.execute_script(js1) >= old_scroll_height: old_scroll_height = browser.execute_script(js1) browser.execute_script(js2) time.sleep(1) sel = Selector(text=browser.page_source) proj_list = sel.xpath('//li[@class="project-li"]')
程序運行結束後,顯示proje_list裏面只有25個元素,而咱們本身手動滾的話卻有100多個,明顯有bug。想定位這個問題很簡單,截圖便可,看看爲何停在第25個項目。對,phantomJs雖然沒有圖形界面,可是能夠截圖。
browser.save_screenshot(debug.png')
這樣就會把圖片保存在項目目錄,打開看看:
發現項目頁只能顯示一行,這說明網頁不兼容phantomJs,這倒不是什麼新鮮事,換一個瀏覽器試試唄。第一期介紹過,selenium是支持全部主流瀏覽器的。好比換成Chrome,只需改一行代碼:
browser = webdriver.Chrome()
再次運行程序,不出所料,Chrome瀏覽器彈出來,不只可以正確顯示頁面,還一直在滾動:
項目全都刷出來了,想爬什麼就爬吧!什麼?你問我在Linux服務器上怎麼爬?純命令行的那種嗎?
PhantomJs是無界面瀏覽器,能夠在Linux服務器上正常運行,但Chrome會在調用GUI接口時報錯。既然Linux服務器沒有圖形接口服務,也就是X Server,咱們就要虛擬出來一個,才能讓Chrome正常運行。因而找到了Xvfb(X virtual frame buffer),它能夠用來做爲完整X服務程序的替代。Xvfb有一個Python的封裝叫PyVirtualDisplay,咱們就用它來解決這個問題。
安裝:
pip install pyvirtualdisplay
用法:
from selenium import webdriver from pyvirtualdisplay import Display display = Display(visible=0, size=(800, 600)) display.start() driver = webdriver.Chrome() driver.get("http://www.baidu.com") print (driver.page_source.encode('utf-8')) driver.quit() display.stop()
運行程序後打印出了baidu的頁面內容,如今能夠完美運行Chrome了。須要補充的是,在Linux上運行Chrome須要額外安裝一個ChromeDriver,比較簡單,就不詳細介紹了。
既然咱們要打造本身的分佈式爬蟲平臺,就要先知道什麼是分佈式系統,百度百科是這樣定義的:
分佈式系統(distributed system)是創建在網絡之上的軟件系統。正是由於軟件的特性,因此分佈式系統具備高度的內聚性和透明性。所以,網絡和分佈式系統之間的區別更多的在於高層軟件(特別是操做系統),而不是硬件。內聚性是指每個數據庫分佈節點高度自治,有本地的數據庫管理系統。透明性是指每個數據庫分佈節點對用戶的應用來講都是透明的,看不出是本地仍是遠程。在分佈式數據庫系統中,用戶感受不到數據是分佈的,即用戶不須知道關係是否分割、有無副本、數據存於哪一個站點以及事務在哪一個站點上執行等。
這個定義不太好理解,看看書上怎麼說。《分佈式系統概念與設計》一書中對分佈式系統作了以下定義:
分佈式系統是一個硬件或軟件組件分佈在不一樣的網絡計算機上,彼此之間僅僅經過消息傳遞進行通訊和協調的系統。
《分佈式系統原理和範型》一書中是這樣定義分佈式系統的:
分佈式系統是若干獨立計算機的集合,這些計算機對於用戶來講就像是單個相關係統。
簡單來講就是一羣獨立計算機集合共同對外提供服務,可是對於系統的用戶來講,就像是一臺計算機在提供服務同樣。分佈式意味着能夠採用更多的普通計算機(相對於昂貴的大型機)組成分佈式集羣對外提供服務。計算機越多,CPU、內存、存儲資源等也就越多,可以處理的併發訪問量也就越大。
從分佈式系統的概念中咱們知道,各個主機之間通訊和協調主要經過網絡進行,因此,分佈式系統中的計算機在空間上幾乎沒有任何限制,這些計算機可能被放在不一樣的機櫃上,也可能被部署在不一樣的機房中,還可能在不一樣的城市中,對於大型的網站甚至可能分佈在不一樣的國家。可是,不管空間上如何分佈,一個標準的分佈式系統應該具備如下幾個主要特徵:
透明性
系統資源被全部計算機共享。每臺計算機的用戶不只可使用本機的資源,還可使用本分佈式系統中其餘計算機的資源。
同一性
系統中的若干臺計算機能夠互相協做來完成一個共同的任務,或者說一個程序能夠分佈在幾臺計算機上並行地運行。
通訊性
系統中的計算機均可以經過通訊來交換信息。
今天先了解下基本概念,熱熱身。整個系統的架構及流程留到下次一塊兒奉上。下期再見!