利用Selenium 能夠驅動瀏覽器執行特定的動做,如點擊、下拉等操做, 同時還能夠獲取瀏覽器當前呈現的頁面的源代碼 ,作到可見便可爬。php
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait browser = webdriver.Chrome() try: browser.get('https://www.baidu.com') input = browser.find_element_by_id('kw') input.send_keys('Python') input.send_keys(Keys.ENTER) wait = WebDriverWait(browser,10) wait.until(EC.presence_of_element_located((By.ID,'content_left'))) print(browser.current_url) print(browser.get_cookies()) print(browser.page_source) finally: browser.close()
運行代碼後,會自動彈出一個 Chrome 瀏覽器。首先會跳轉到百度,而後在搜索框中輸入 Python,接着跳轉到搜索頁。 搜索結果加載出來後,控制檯分別會輸出當前的 URL 、當前的 Cookies 和網頁源代碼.
css
若是用 Selenium 來驅動瀏覽器加載網頁的話,就能夠直接拿到 JavaScript 渲染的結果,不用擔憂使用的是什麼加密系統。聲明瀏覽器對象 html
from selenium import webdriver
browser = webdriver.Chrome() browser = webdriver.Firefox() browser = webdriver.Edge() browser = webdriver.PhantomJS() browser = webdriver.Safari()
瀏覽器對象的初始化並將其賦值爲 browser對象。接下來,就是調用 browser 對象,讓其執行各個動做以模擬瀏覽器操做python
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.taobao.com/') print(browser.page_source)
彈出了 Chrome 瀏覽器而且自動訪問了淘寶,而後控制檯輸出了淘寶頁面的源代碼, 隨後瀏覽器關閉。能夠實現瀏覽器的驅動並獲取網頁源碼jquery
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.taobao.com') input_first = browser.find_element_by_id('q') input_second = browser.find_element_by_xpath('//*[@id ="q"]') input_third = browser.find_element_by_css_selector('#q') print(input_first, input_second, input_third) browser.close()
這裏使用 3 種方式獲取輸入框,分別根據 ID, CSS 選擇器和 XPath 獲取,它們返回的結果徹底一致。web
from selenium import webdriver from selenium.webdriver.common.by import By browser = webdriver.Chrome() browser.get('https://www.taobao.com') input_first = browser.find_element(By.ID, 'q') print(input_first) browser.close()
查找方式的功能與上面列舉函數一致,參數更加靈活。api
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.taobao.com') lis = browser.find_elements_by_css_selector('.service-bd li') print(lis) browser.close()
獲得的內容變成了列表類型,列表中的每一個節點都是 WebElement 類型。瀏覽器
若是用 find_element()方法,只能獲取匹配的第一個節點,結果是 WebElement類型。若是用 find_elements()方法,結果是列表類型,列表中的每一個節點是 WebElement 類型。from selenium import webdriver import time browser = webdriver.Chrome() browser.get('https://www.taobao.com') input = browser.find_element_by_id('q') input.send_keys('iPhone') time.sleep(1) input.clear() input.send_keys('iPad') button = browser.find_element_by_class_name('btn-search') button.click()
首先驅動瀏覽器打開淘寶,用 find_element_by_id()方法獲取輸入框,再用 send_keys() 方法輸入 iPhone 文字,等待秒後用 clear()方法清空輸入框,再次調用 send_keys()方法輸入 iPad 文字,以後再 find_element_by_class_name()方法獲取搜索按鈕,最後調用 click ()方法完成搜索動做。cookie
更多的操做參見官方文檔交互動做介紹:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webelement。框架
from selenium import webdriver from selenium.webdriver import ActionChains browser = webdriver.Chrome() url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable' browser.get(url) browser.switch_to.frame('iframeResult') source = browser.find_element_by_css_selector('#draggable') target = browser.find_element_by_css_selector('#droppable') actions = ActionChains(browser) actions.drag_and_drop(source.target) actions.perform
打開網頁中一個拖曳實例,依次選中要拖曳的節點和拖曳到的目標節點,接着聲明 ActionChains 對象並將其賦值爲 actions 變量,而後調用 actions 變量的 drag_and_drop()方法,再調 perform()方法執行動做。
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.zhihu.com/explore') browser.execute_script('window.scrollTo(0,document.body.scrollHeight)') browser.execute_script('alert("To Bottom")')
from selenium import webdriver browser = webdriver.Chrome() url = 'https://zhihu.com/explore' browser.get(url) logo = browser.find_element_by_id('zh-top-link-logo') print(logo) print(logo.get_attribute('class'))
結果獲取知乎的 logo 節點,最後打印出它的 class。
經過 get_attribute()方法,而後傳人想要獲取的屬性名,就能夠獲得它的值了from selenium import webdriver browser = webdriver.Chrome() url = 'https://www.zhihu.com/explore' browser.get(url) input = browser.find_element_by_class_name('zu-top-add-question') print(input.text)
from selenium import webdriver browser =webdriver.Chrome() url = 'https://www.zhihu.com/explore' browser.get(url) input = browser.find_element_by_class_name('zu-top-add-question') print(input.text) print(input.id) print(input.location) print(input.size) print(input.tag_name)
首先得到「提問」按鈕節點,再調用其 id、location、tag_name、size 屬性來獲取對應的屬性值
切換Frame
網頁中有種節點叫做 iframe,也就是子 Frame,至關於頁面的子頁面,它的結構和外部網頁的結構徹底一致。Selenium 打開頁面後,默認在父級 Frame 裏面操做,而此時若是頁面中還有子Frame,是不能獲取到子 Frame 裏面的節點的。這時就須要使用 switch_to.frame()方法來切換Frame。示例:
import time from selenium import webdriver from selenium.common.exceptions import NoSuchElementException browser = webdriver.Chrome() url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable' browser.get(url) browser.switch_to.frame('iframeResult') try: logo = browser.find_element_by_class_name('logo') except NoSuchElementException: print('NO LOGO') browser.switch_to.parent_frame() logo = browser.find_element_by_class_name('logo') print(logo) print(logo.text)
之前面動做鏈操做的網頁例,首先經過 switch_to.frame()方法切換到子 Frame 裏,再嘗試獲取父級 Frame 裏的 logo 節點(這是不能找到的),若是找不到的話,就會拋出 NoSuchEle entException 異常,異常被捕捉以後,就會輸出 NO LOGO。接下來,從新切換父級 Frame, 而後再次從新獲取節點,發現此時能夠成功獲取了。
當頁面中包含子 Frame 時,若是想獲取子 Frame 中的節點,須要先調用 switch_to.frame() 方法切換到對應的 Frame,再進行操做。from selenium import webdriver browser = webdriver.Chrome() browser.implicitly_wait(10) browser.get('https://www.zhihu.com/explore') input = browser.find_element_by_class_name('zu-top-add-question') print(input)
用 implicitly_wait()方法實現隱式等待。
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC browser = webdriver.Chrome() browser.get('https://www.taobao.com/') wait = WebDriverWait(browser,10) input = wait.until(EC.presence_of_element_located((By.ID, 'q'))) button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search'))) print(input, button)
首先引人 WebDriverWait 對象,指定最長等待時間,調用 until()方法,傳人要等待條件 expected_conditions。如:傳入 presence_of_element_located 條件,表明節點出出現意思,參數是節點的定位元組,也就是 ID 爲 q 的節點搜索框。
效果:在 10 秒內若是 ID 爲 q的節點(搜索框)成功加載出來,就返回該節點;若是超過 10 秒尚未加載出來,就拋出異常。import time from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.baidu.com/') browser.get('https://www.taobao.com/') browser.get('https://www.python.org/') browser.back() time.sleep(1) browser.forward() browser.close()
連續訪問3個頁面,調用 back()方法回到第二個頁面,再調用 forward()方法前進到第 3個頁面。
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.zhihu.com/explore') print(browser.get_cookies()) browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'}) print(browser.get_cookies()) browser.delete_all_cookies() print(browser.get_cookies())
訪問知乎,加載完成後,瀏覽器已經生成 Cookies。調用 get_cookies() 方法獲取全部的 Cookies。而後,添加一個 Cookie,傳入一個字典,有name、domain、value內容。再次獲取全部 Cookies。結果就多了新加的 Cookie。調用 delete_all_cookies()方法刪除全部 Cookies。再從新獲取,結果就爲空了。
import time from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.baidu.com') browser.execute_script('window.open()') print(browser.window_handles) browser.switch_to_window(browser.window_handles[1]) browser.get('https://www.taobap.com') time.sleep(1) browser.switch_to_window(browser.window_handles[0]) browser.get('https://python.org')
首先訪問百度,而後調用 execute_script()方法,傳入 window.open()這個 JavaScript 語句新開啓一個選項卡。接下來,想切換到該選項卡,調用 window_handles 屬性獲取當前開啓的全部選項卡,返回的是選項卡的代號列表。要想切換選項卡,只須要調用 switch_to_window()方法便可,其中參數是選項卡的代號。將第二個選項卡代號傳人,即跳轉到第二個選項卡,接下來在第二個選項卡下打開一個新頁面,而後切換回第一個選項卡從新調用 switch_to_window()方法,再執行其餘操做。
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.baidu.com') browser.find_element_by_id('hello')
首先打開百度頁面,嘗試選擇一個並不存在的節點 ,此時就會遇到異常。捕獲異常示例:
from selenium import webdriver from selenium.common.exceptions import TimeoutException, NoSuchElementException browser = webdriver.Chrome() try: browser.get('https://www.baidu.com') except TimeoutException: print('Timeout') try: browser.find_element_by_id('hello') except NoSuchElementException: print('No Element') finally: browser.close()
這裏使用 try except 來捕獲各種異常。如,對 find_element_by_id()查找節點方法捕獲 NoSuchElementException 異常,一旦出現這樣的錯誤,就進行異常處理,程序也不會中斷。