標籤:
本文和大家分享的主要是python 爬蟲 利器Selenium的相關內容,一起來看看吧,希望對大家 學習python爬蟲有所協助。Selenium 是什嗎?一句話,自動化測試載入器。它支援各種瀏覽器,包括 Chrome , Safari , Firefox 等主流介面式瀏覽器,如果你在這些瀏覽器裡面安裝一個 Selenium 的外掛程式,那麼便可以方便地實現 Web介面的測試。換句話說叫 Selenium 支援這些瀏覽器驅動。話說回來, PhantomJS 不也是一個瀏覽器嗎,那麼 Selenium 支援不?答案是肯定的,這樣二者便可以實現無縫對接了。然後又有什麼好訊息呢?Selenium 支援多種語言開發,比如 Java , C , Ruby 等等,有 Python 嗎?那是必須的!哦這可真是天大的好訊息啊。嗯,所以呢?安裝一下 Python 的 Selenium 庫,再安裝好 PhantomJS ,不就可以實現 Python +Selenium + PhantomJS 的無縫對接了嘛! PhantomJS 用來渲染解析 JS , Selenium 用來驅動以及與 Python 的對接, Python 進行後期的處理,完美的三劍客!有人問,為什麼不直接用瀏覽器而用一個沒介面的 PhantomJS 呢?答案是:效率高!Selenium 有兩個版本,目前最新版本是 2.53.1 ( 2016/3/22 ) SeleniumSelenium 2 ,又名 WebDriver ,它的主要新功能是整合了 Selenium 1.0 以及 WebDriver (WebDriver 曾經是 Selenium 的競爭者)。也就是說 Selenium 2 是 Selenium 和 WebDriver 兩個項目的合并,即 Selenium 2 相容 Selenium ,它既支援 Selenium API 也支援 WebDriver API 。 查看詳情說明 Webdriver嗯,通過以上描述,我們應該對 Selenium 有了大概對認識,接下來就讓我們開始進入動態爬取的新世界吧。本文參考內容來自 Selenium 官網 SeleniumPython 文檔安裝首先安裝 Selenium pip install selenium快速開始 初步體驗我們先來一個小例子感受一下 Selenium ,這裡我們用 Chrome 瀏覽器來測試,方便查看效果,到真正爬取的時候換回 PhantomJS 即可。from selenium import webdriverbrowser = webdriver.Chrome()browser. get(’http://www.baidu.com/’)運行這段代碼,會自動開啟瀏覽器,然後訪問百度。如果程式執行錯誤,瀏覽器沒有開啟,那麼應該是沒有裝 Chrome 瀏覽器或者 Chrome 驅動沒有配置在環境變數裡。下載驅動,然後將驅動檔案路徑配置在環境變數即可。瀏覽器驅動下載: https://sites.google.com/a/chromium.org/chromedriver/downloads比如我的是 Mac OS ,就把下載好的檔案放在 /usr/bin 目錄下就可以了。 類比提交下面的代碼實現了類比提交提交搜尋的功能,首先等頁面載入完成,然後輸入到搜尋方塊文本,點擊提交。from selenium import webdriverfrom selenium.webdriver.common.keys import Keysdriver = webdriver.Chrome()driver. get("http://www.python.org")assert "Python" in driver.titleelem = driver.find_element_by_name("q")elem.send_keys("pycon")elem.send_keys(Keys.RETURN)print driver.page_source同樣是在 Chrome 裡面測試,感受一下。 執行個體說明其中 driver.get 方法會開啟請求的 URL , WebDriver 會等待頁面完全載入完成之後才會返回,即程式會等待頁面的所有內容載入完成, JS 渲染完畢之後才繼續往下執行。注意:如果這裡用到了特別多的 Ajax 的話,程式可能不知道是否已經完全載入完畢。WebDriver 提供了許多尋找網頁元素的方法,譬如 find_element_by_* 的方法。例如一個輸入框可以通過 find_element_by_name 方法尋找 name 屬性來確定。然後我們輸入來文本然後類比點擊了斷行符號,就像我們敲擊鍵盤一樣。我們可以利用 Keys 這個類來類比鍵盤輸入。最後最重要的一點,擷取網頁渲染後的原始碼,輸出 page_source 屬性即可。這樣,我們就可以做到網頁的動態爬取了。 測試案例有了以上特性,我們當然可以用來寫測試範例了。 import unittest from selenium import webdriver from selenium.webdriver.common.keys import Keys class PythonOrgSearch(unittest.TestCase): def setUp(self):self.driver = webdriver.Chrome() def test_search_in_python_org(self):driver = self.driverdriver.get("http://www.python.org")self.assertIn("Python", driver.title)elem = driver.find_element_by_name("q")elem.send_keys("pycon")elem.send_keys(Keys.RETURN) assert "No results found." not in driver.page_source def tearDown(self):self.driver.close() if __name__ == "__main__":unittest.main()運行程式,同樣的功能,我們將其封裝為測試標準類的形式。 測試案例測試案例是繼承了 unittest.TestCase 類,繼承這個類表明這是一個測試類別。 setUp 方法是初始化的方法,這個方法會在每個測試類別中自動調用。每一個測試方法命名都有規範,必須以 test 開頭,會自動執行。最後的 tearDown 方法會在每一個測試方法結束之後調用。這相當於最後的析構方法。在這個方法裡寫的是 close 方法,你還可以寫 quit 方法。不過 close 方法相當於關閉了這個 TAB 選項卡,然而 quit 是退出了整個瀏覽器。當你只開啟了一個 TAB 選項卡的時候,關閉的時候也會將整個瀏覽器關閉。頁面操作 頁面互動僅僅抓取頁面沒有多大卵用,我們真正要做的是做到和頁面互動,比如點擊,輸入等等。那麼前提就是要找到頁面中的元素。WebDriver 提供了各種方法來尋找元素。例如下面有一個表單輸入框。<input type="text" name="passwd" id="passwd-id" />我們可以這樣擷取它element = driver.find_element_by_id("passwd-id")element = driver.find_element_by_name("passwd")element = driver.find_elements_by_tag_name("input")element = driver.find_element_by_xpath("//input[@id=’passwd-id’]")你還可以通過它的文本連結來擷取,但是要小心,文本必須完全符合才可以,所以這並不是一個很好的匹配方式。而且你在用 xpath 的時候還需要注意的是,如果有多個元素匹配了 xpath ,它只會返回第一個匹配的元素。如果沒有找到,那麼會拋出 NoSuchElementException 的異常。擷取了元素之後,下一步當然就是向文本輸入內容了,可以利用下面的方法 element.send_keys("some text")同樣你還可以利用 Keys 這個類來類比點擊某個按鍵。 element.send_keys("and some", Keys.ARROW_DOWN)你可以對任何擷取到到元素使用 send_keys 方法,就像你在 GMail 裡面點擊發送鍵一樣。不過這樣會導致的結果就是輸入的文本不會自動清除。所以輸入的文本都會在原來的基礎上繼續輸入。你可以用下面的方法來清除輸入文本的內容。 element.clear()這樣輸入的文本會被清除。 填充表單我們已經知道了怎樣向文字框中輸入文字,但是其它的表單元素呢?例如下拉選項卡的的處理可以如下element = driver.find_element_by_xpath("//select[@name=’name’]")all_options = element.find_elements_by_tag_name("option") for option in all_options:print("Value is: %s" % option.get_attribute("value")) option.click()首先擷取了第一個 select 元素,也就是下拉選項卡。然後輪流設定了 select 選項卡中的每一個 option 選項。你可以看到,這並不是一個非常有效方法。其實 WebDriver 中提供了一個叫 Select 的方法,可以協助我們完成這些事情。 from selenium.webdriver.support.ui import Selectselect =Select(driver.find_element_by_name(’name’)) select.select_by_index(index)select.select_by_visible_text("text") select.select_by_value(value)如你所見,它可以根據索引來選擇,可以根據值來選擇,可以根據文字來選擇。是十分方便的。全部取消選擇怎麼辦呢?很簡單 select = Select(driver.find_element_by_id(’id’)) select.deselect_all()這樣便可以取消所有的選擇。另外我們還可以通過下面的方法擷取所有的已選選項。select = Select(driver.find_element_by_xpath("xpath"))all_selected_options = select.all_selected_options擷取所有可選選項是 options = select.options如果你把表單都填好了,最後肯定要提交表單對吧。怎嗎提交呢?很簡單 driver.find_element_by_id("submit").click()這樣就相當於類比點擊了 submit 按鈕,做到表單提交。當然你也可以單獨提交某個元素 element.submit()方法,WebDriver 會在表單中尋找它所在的表單,如果發現這個元素並沒有被表單所包圍,那麼程式會拋出 NoSuchElementException 的異常。 元素拖拽要完成元素的拖拽,首先你需要指定被拖動的元素和拖動目標元素,然後利用 ActionChains 類來實現。element = driver.find_element_by_name("source")target = driver.find_element_by_name("target")from selenium.webdriver import ActionChainsaction_chains = ActionChains(driver)action_chains.drag_and_drop(element, target).perform()這樣就實現了元素從 source 拖動到 target 的操作。 頁面切換一個瀏覽器肯定會有很多視窗,所以我們肯定要有方法來實現視窗的切換。切換視窗的方法如下 driver.switch_to_window("windowName")另外你可以使用 window_handles 方法來擷取每個視窗的操作對象。例如 for handle in driver.window_handles:driver.switch_to_window(handle)另外切換 frame 的方法如下 driver.switch_to_frame(" frameName.0.child")這樣焦點會切換到一個 name 為 child 的 frame 上。 彈窗處理當你出發了某個事件之後,頁面出現了彈窗提示,那麼你怎樣來處理這個提示或者擷取提示資訊呢?alert = driver.switch_to_alert()通過上述方法可以擷取彈窗對象。 記錄那麼怎樣來操作頁面的前進和後退功能呢? driver.forward() driver.back()嗯,簡潔明了。 Cookies處理為頁面添加 Cookies ,用法如下# Go to the correct domaindriver.get("http://www.example.com")# Now set the cookie. This one’s valid for the entire domaincookie = {‘name’ : ‘foo’, ‘value’ : ‘bar’}driver.add_cookie(cookie)擷取頁面 Cookies ,用法如下# Go to the correct domaindriver.get("http://www.example.com")# And now output all the available cookies for the current URLdriver.get_cookies()以上便是 Cookies 的處理,同樣是非常簡單的。 元素選取關於元素的選取,有如下的API單個元素選取 find_element_by_idfind_element_by_namefind_element_by_xpathfind_element_by_link_textfind_element_by_partial_link_textfind_element_by_tag_namefind_element_by_class_namefind_element_by_css_selector多個元素選取 find_elements_by_namefind_elements_by_xpathfind_elements_by_link_textfind_elements_by_partial_link_textfind_elements_by_tag_namefind_elements_by_class_namefind_elements_by_css_selector另外還可以利用 By 類來確定哪種選擇方式 from selenium.webdriver.common. by import Bydriver.find_element( By.XPATH, ’//button[text()="Some text"]’)driver.find_elements( By.XPATH, ’//button’)By 類的一些屬性如下 ID = "id"XPATH = "xpath"LINK_TEXT = "link text"PARTIAL_LINK_TEXT = "partial link text"NAME = "name"TAG_NAME = "tag name"CLASS_NAME = "class name"CSS_SELECTOR = "css selector"更詳細的元素選擇方法參見官方文件項目選擇: http://selenium-python.readthedocs.org/en/latest/locating-elements.html頁面等待這是非常重要的一部分,現在的網頁越來越多採用了 Ajax 技術,這樣程式便不能確定何時某個元素完全載入出來了。這會讓元素定位困難而且會提高產生 ElementNotVisibleException 的機率。所以 Selenium 提供了兩種等待方式,一種是隱式等待,一種是顯式等待。隱式等待是等待特定的時間,顯式等待是指定某一條件直到這個條件成立時繼續執行。 顯式等待顯式等待指定某個條件,然後設定最長等待時間。如果在這個時間還沒有找到元素,那麼便會拋出異常了。 from selenium import webdriver from selenium.webdriver.common. by import Byfrom selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as ECdriver = webdriver.Chrome()driver. get("http://somedomain/url_that_delays_loading") try:element = WebDriverWait(driver, 10). until(EC.presence_of_element_located(( By.ID, "myDynamicElement"))) finally:driver.quit()程式預設會 500ms 調用一次來查看元素是否已經產生,如果本來元素就是存在的,那麼會立即返回。下面是一些內建的等待條件,你可以直接調用這些條件,而不用自己寫某些等待條件了。 等待條件title_istitle_containspresence_of_element_locatedvisibility_of_element_locatedvisibility_ofpresence_of_all_elements_locatedtext_to_be_present_in_elementtext_to_be_present_in_element_valueframe_to_be_available_and_switch_to_itinvisibility_of_element_locatedelement_to_be_clickable – it is Displayed and Enabled.staleness_ofelement_to_be_selectedelement_located_to_be_selectedelement_selection_state_to_beelement_located_selection_state_to_bealert_is_present from selenium.webdriver.sup port import expected_conditions as ECwait = WebDriverWait(driver, 10)element = wait.until(EC.element_to_be_clickable((By.ID,’someid’)))from selenium.webdriver.support import expected_conditions as ECwait = WebDriverWait(driver, 10)element = wait.until(EC.element_to_be_clickable((By.ID,’someid’))) 隱式等待隱式等待比較簡單,就是簡單地設定一個等待時間,單位為秒。 from selenium import webdriverdriver = webdriver.Chrome()driver.implicitly_wait(10) # secondsdriver.get("http://somedomain/url_that_delays_loading")myDynamicElement = driver.find_element_by_id("myDynamicElement")當然如果不設定,預設等待時間為0 。程式架構對於頁面測試和分析,官方提供了一個比較明晰的代碼結構,可以參考。結語以上就是 Selenium 的基本用法,我們講解了頁面互動,頁面渲染之後的原始碼的擷取。這樣,即使頁面是 JS 渲染而成的,我們也可以手到擒來了。就是這麼溜!來源:網路
Python爬蟲利器:Selenium的用法