Ajax數(shù)據(jù)爬取及selenium的使用詳解

一讶泰、什么是AJAX

AJAX[1],全稱(chēng)Asynchronous JavaScript And XML拂到,即異步的JavaScript和XML痪署。通過(guò)在后臺(tái)與服務(wù)器進(jìn)行少量的數(shù)據(jù)交換,AJAX可以使網(wǎng)頁(yè)實(shí)現(xiàn)異步更新兄旬,實(shí)現(xiàn)網(wǎng)頁(yè)的動(dòng)態(tài)渲染狼犯。

這意味著可以在不加載整個(gè)網(wǎng)頁(yè)的情況下,對(duì)網(wǎng)頁(yè)的某部分進(jìn)行更新。而傳統(tǒng)的網(wǎng)頁(yè)如果需要更新內(nèi)容,則必須重載整個(gè)網(wǎng)頁(yè)頁(yè)面悯森。

使用AJAX加載的網(wǎng)頁(yè)數(shù)據(jù)宋舷,雖然將數(shù)據(jù)渲染到了瀏覽器中,但在網(wǎng)頁(yè)源代碼中還是看不到通過(guò)ajax加載的數(shù)據(jù)呐馆,只能看到通過(guò)url加載的數(shù)據(jù)肥缔,這使得通過(guò)requests、urllib無(wú)法正常獲取網(wǎng)頁(yè)的全部數(shù)據(jù)汹来。

獲取ajax數(shù)據(jù)的兩種方式:

  1. 直接分析ajax調(diào)用的接口,然后通過(guò)代碼請(qǐng)求這個(gè)接口
    優(yōu)點(diǎn):可以直接請(qǐng)求到數(shù)據(jù),不需要做一些解析工作改艇,代碼量少收班,性能高。
    缺點(diǎn):分析接口比較復(fù)雜谒兄,特別是一些通過(guò)js混淆的接口摔桦,需要一定的js功底,容易被發(fā)現(xiàn)是爬蟲(chóng)承疲。
  1. 使用selenium+driver(瀏覽器驅(qū)動(dòng))模擬瀏覽器行為獲取數(shù)據(jù)
    優(yōu)點(diǎn):瀏覽器能請(qǐng)求到的數(shù)據(jù)邻耕,使用selenium也能請(qǐng)求到,爬蟲(chóng) 更穩(wěn)定燕鸽,且適用于所有類(lèi)型的動(dòng)態(tài)渲染網(wǎng)頁(yè)[2]兄世。
    缺點(diǎn):代碼量多,性能低啊研。

二御滩、selenium+chromedriver獲取動(dòng)態(tài)數(shù)據(jù)

selenium是一個(gè)自動(dòng)化測(cè)試工具,可以模擬人類(lèi)在瀏覽器上的一些行為党远,自動(dòng)處理瀏覽器上的一些行為削解,比如點(diǎn)擊、填充數(shù)據(jù)等沟娱。還可以獲取瀏覽器當(dāng)前呈現(xiàn)的頁(yè)面源碼氛驮,解決動(dòng)態(tài)渲染網(wǎng)頁(yè)的數(shù)據(jù)抓取,做到可見(jiàn)即可爬济似。

而chromedriver是一個(gè)驅(qū)動(dòng)Chrome瀏覽器的驅(qū)動(dòng)程序矫废,selenium使用它才能夠驅(qū)動(dòng)Chrome瀏覽器。
針對(duì)不同的瀏覽器有不同的驅(qū)動(dòng)(driver),比如Firefox的驅(qū)動(dòng)geckodriver碱屁、IE的驅(qū)動(dòng)IEdriver等磷脯,都可以配合selenium驅(qū)動(dòng)對(duì)應(yīng)的瀏覽器,本文以Chrome瀏覽器為例娩脾。

安裝Selenium+chromedriver:

  1. 安裝selenium模塊:pip install selenium
  2. 安裝chromedriver驅(qū)動(dòng):下載chromedriver驅(qū)動(dòng)后赵誓,放到不需要權(quán)限的純英文目錄下即可,但每次使用都需要指定驅(qū)動(dòng)的絕對(duì)路徑。也可以放到python的Scripts目錄下(推薦)俩功,或者將其路徑添加到環(huán)境變量中幻枉,這樣每次使用也都無(wú)需指定路徑。

三诡蜓、selenium使用詳解

入門(mén)檢測(cè):

from selenium import webdriver

#聲明瀏覽器對(duì)象
#chromedriver驅(qū)動(dòng)已放入Python的Scripts目錄熬甫,故無(wú)需再指定路徑
driver= webdriver.Chrome()
#請(qǐng)求網(wǎng)頁(yè)(適用所有請(qǐng)求類(lèi)型)
driver.get('https://www.baidu.com/')
#獲取當(dāng)前瀏覽器渲染后的HTML代碼
print( driver.page_source )  
#關(guān)閉當(dāng)前頁(yè)面
driver.close()
#關(guān)閉整個(gè)瀏覽器
driver.quit()   

selenium的常用操作:

(一)、定位元素:

定位單個(gè)元素:find_element
  1. find_element_by_id:根據(jù)id來(lái)查找某個(gè)元素蔓罚。
    第一種方式:div_tag = driver.find_element_by_id('su')
    第二種方式:div_tag = driver.find_element(By.ID, 'su')
    注意:二者效果等價(jià)椿肩,推薦使用第一種。
    使用第二種方式需要先導(dǎo)入By類(lèi)
    from selenium.webdriver.common.by import By

  1. find_element_by_class_name:根據(jù)類(lèi)名來(lái)查找某個(gè)元素豺谈。driver.find_element_by_class_name('su')
    driver.find_element(By.CLASS_NAME, 'su')

  1. find_element_by_name:根據(jù)name屬性值查找某個(gè)元素郑象。
    driver.find_element_by_name('emile')
    driver.find_element(By.NAME, 'emile')

  1. find_element_by_tag_name:根據(jù)標(biāo)簽名來(lái)查找某個(gè)元素。
    driver.find_element_by_tag_name('div')
    driver.find_element(By.TAG_NAME, 'div')

  1. find_element_by_xpath:根據(jù)xpath語(yǔ)法查找某個(gè)元素茬末。
    driver.find_element_by_xpath('//div')
    driver.find_element(By.XPATH, '//div')

  1. find_element_by_css_selector:根據(jù)css選擇器選取元素厂榛。
    driver.find_element_by_css_selector('//div')
    driver.find_element(By.CSS_SELECTOR, '//div')
定位多個(gè)元素:find_elements

find_element_by_id:根據(jù)id來(lái)查找某個(gè)元素
find_elements_by_class_name:根據(jù)類(lèi)名來(lái)查找某個(gè)元素
find_elements_by_name:根據(jù)name屬性的值來(lái)查找某個(gè)元素
find_elements_by_tag_name:根據(jù)標(biāo)簽名來(lái)查找某個(gè)元素
find_elements_by_xpath:根據(jù)xpath語(yǔ)法來(lái)查找某個(gè)元素
find_elements_by_css_selector:根據(jù)css選擇器來(lái)選取某個(gè)元素

注意:
  1. find_elements與find_element用法一致,只是多了一個(gè)s丽惭!
  2. find_element是獲取第一個(gè)滿足條件的元素,直接返回獲取到的元素對(duì)象,如果找不到,則報(bào)錯(cuò)击奶!
  3. find_elements是獲取所有滿足條件的元素,返回獲取到的所有元素對(duì)象組成的列表,如果找不到,返回空列表!

(二)责掏、操作表單元素

常見(jiàn)的表單元素:

  • 輸入框:input type='text/password/email/number'
  • 按鈕:button柜砾、input type='submit'
  • 復(fù)選框:checkbox、input type='checkbox'
  • 下拉列表:select
  1. 操作輸入框input:
    第一步:定位標(biāo)簽拷橘;
    第二步:使用send_keys(value)將數(shù)據(jù)填入輸入框局义。

  2. 操作按鈕button:
    第一步:定位標(biāo)簽;
    第二步:執(zhí)行click()點(diǎn)擊事件冗疮。

  3. 操作復(fù)選框checkbox:
    第一步:定位標(biāo)簽萄唇;
    第二步:執(zhí)行click()點(diǎn)擊事件。
    如果默認(rèn)是未選中,則點(diǎn)擊后選中,再次點(diǎn)擊則取消選中术幔!

  4. 操作下拉列表select:
    select的元素不能直接點(diǎn)擊另萤,因?yàn)樾枰冗x中元素。
    第一步:定位select標(biāo)簽
    第二步:導(dǎo)入類(lèi) selenium.webdriver.support.ui.Select
    第三步:將獲取到的元素當(dāng)做參數(shù)傳入這個(gè)類(lèi)中诅挑,創(chuàng)建Select對(duì)象
    第四步:使用這個(gè)對(duì)象選擇下拉列表中的選項(xiàng)

示例1:

from selenium import webdriver
from selenium.webdriver.support.ui import Select
import time

driver = webdriver.Chrome() 
#請(qǐng)求網(wǎng)頁(yè)
driver.get('https://hao.#/') 

#選中輸入框
input_tag = driver.find_element_by_id('search-kw') 
#發(fā)送數(shù)據(jù)
input_tag.send_keys('python')
time.sleep(3)
#清除輸入框數(shù)據(jù)
input_tag.clear()

#選中按鈕
button_tag = driver.find_element_by_id('search-btn')
#點(diǎn)擊按鈕
button_tag.click()   
time.sleep(2)

#注意:此時(shí)select元素處于隱藏狀態(tài)的div元素內(nèi)四敞,
#需要點(diǎn)擊激活div元素,然后才能定位到select元素
div_tag = driver.find_element_by_id('email')
div_tag.click()
select_tag = driver.find_element_by_id('mail-opts')

#將選中的下拉列表元素拔妥,傳入Select類(lèi)中忿危,創(chuàng)建Select對(duì)象
select = Select( select_tag  )

#根據(jù)索引選擇下拉列表的選項(xiàng)(注意:選中相當(dāng)于點(diǎn)擊!)
select_index = select .select_by_index(1)
#根據(jù)value屬性選擇
select .select_by_value('@163.com 網(wǎng)易')
#根據(jù)可見(jiàn)文本選擇
select .select_by_visible_text('@126.com 網(wǎng)易')

#取消所有選中項(xiàng)  
select .deselect_all() 

driver.quit()

示例2:

from selenium import webdriver
driver = webdriver.Chrome() 
driver.get('http://www.reibang.com/sign_in') 
#選中復(fù)選框
check_tag =driver.find_element_by_id('session_remember_me')
#點(diǎn)擊復(fù)選框
check_tag.click() 
driver.quit()

(三)、行為鏈ActionChains

有時(shí)候在頁(yè)面中的操作需要多個(gè)步驟没龙,這個(gè)時(shí)候可以使用鼠標(biāo)行為鏈類(lèi)ActionChains來(lái)統(tǒng)一完成铺厨。

比如將鼠標(biāo)移動(dòng)到某個(gè)元素上并執(zhí)行點(diǎn)擊事件缎玫,示例代碼如下:

import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains

driver = webdriver.Chrome()
driver.get('https://baidu.com/')

#選中輸入框
input_tag = driver.find_element_by_id('kw')  
#選中按鈕
button_tag = driver.find_element_by_id('su')  

#創(chuàng)建行為鏈對(duì)象
actions = ActionChains(driver)

#移動(dòng)到某個(gè)元素
actions.move_to_element(input_tag) 
#向某個(gè)元素發(fā)送數(shù)據(jù)
actions.send_keys_to_element(input_tag,  'python') 
#移動(dòng)鼠標(biāo)到某個(gè)元素
actions.move_to_element(button_tag)  
#點(diǎn)擊某個(gè)元素
actions.click(button_tag) 

#執(zhí)行這個(gè)行為鏈
actions.perform() 

time.sleep(3)
driver.quit()

其他操作
actions.click_and_hold(on_element=None) 點(diǎn)擊但不松開(kāi)鼠標(biāo)
actions.context_click(on_element=None) 右擊
actions.double_click(on_element=None) 雙擊
actions.drag_and_drop(source, target) 拖拽
更多見(jiàn)官方文檔api


(四)、網(wǎng)頁(yè)的Cookie操作

注意:只能獲取當(dāng)前網(wǎng)頁(yè)的Cookie信息,而獲取不到其他網(wǎng)頁(yè)的cookie信息解滓。

示例代碼:

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://baidu.com/')

# 1. 獲取所有的cookies
for cookie in driver.get_cookies():
    print(cookie)

# 2. 根據(jù)cookie的name獲取某條cookie
print( driver.get_cookie(name='delPer') )

# 3. 根據(jù)cookie的name刪除某條cookie
driver.delete_cookie('delPer')
print( driver.get_cookie(name='delPer') )

# 4. 刪除所有的cookie
driver.delete_all_cookies()

# 5. 添加cookie
driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/'})
print( driver.get_cookies() )


(五)赃磨、頁(yè)面等待

現(xiàn)在網(wǎng)頁(yè)越來(lái)越多的采用了Ajax技術(shù),這樣程序便不能確定某個(gè)元素何時(shí)才能完全加載出來(lái)洼裤。如果程序定位某個(gè)元素時(shí)邻辉,實(shí)際頁(yè)面中這個(gè)元素還未完全加載進(jìn)來(lái),此時(shí)便會(huì)拋出NoSuchElementException異常腮鞍。為了解決這個(gè)問(wèn)題值骇,selenium提供了兩種等待方式:隱式等待、顯示等待移国。

1.隱式等待:

調(diào)用driver.implicitly_wait(n)雷客,在定位元素之前直接等待n秒,如果等待n秒之后仍然定位不到元素桥狡,則報(bào)錯(cuò)。

2.顯式等待:

在指定時(shí)間內(nèi)皱卓,一直等待某個(gè)條件成立裹芝,條件成立后立即執(zhí)行定位元素的操作;如果超過(guò)這個(gè)時(shí)間條件仍然沒(méi)有成立娜汁,則會(huì)拋出異常嫂易!

顯式等待需要使用selenium.webdriver.support.excepted_conditions期望條件
selenium.webdriver.support.ui.WebDriverWait類(lèi)來(lái)配合完成。

示例代碼:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome()
driver.get('https://www.douban.com/')

# 隱式等待:直接等待10秒鐘
driver.implicitly_wait(10) 
# 執(zhí)行定位元素操作
driver.find_element(By.ID, 'hahahah')

# 顯式等待:條件成立掐禁,立即執(zhí)行怜械;超過(guò)指定時(shí)間則報(bào)錯(cuò)
element = WebDriverWait(driver, 10).until(
      EC.presence_of_element_located( (By.ID, 'form_email') ) 
      #注意:傳入的定位條件必須是元組形式
)

常見(jiàn)的等待條件
presence_of_element_located:某個(gè)元素已經(jīng)加載出來(lái)了
presence_of_all_elements_located :所有符合條件的元素都加載完畢了
element_to_be_clickable:某個(gè)元素可以被點(diǎn)擊了
visibility_of_element_located :某個(gè)元素可以看見(jiàn)了
frame_to_be_available_and_switch_to_it:某個(gè)子網(wǎng)頁(yè)一旦可以切換了就切換過(guò)去。
更多見(jiàn)官網(wǎng)


(六)傅事、切換窗口:switch_to.window

有時(shí)候?yàn)g覽器存在多個(gè)窗口缕允,如果需要在不同窗口進(jìn)行操作,就需要在程序中切換窗口蹭越。selenium提供了switch_to.window方法來(lái)切換窗口障本,而具體切換到哪個(gè)窗口,可以通過(guò)driver.window_handles查看所有窗口對(duì)象响鹃。

示例代碼:

from selenium import webdriver

driver = webdriver.Chrome()
# 1.打開(kāi)百度首頁(yè)
driver.get('https://baidu.com/') 
# 2.在當(dāng)前瀏覽器中打開(kāi)一個(gè)新的窗口驾霜,并打開(kāi)豆瓣網(wǎng)。
driver.execute_script( 'window.open("https://www.douban.com/")')

print( '當(dāng)前url:', driver.current_url )
#注意:列表會(huì)按照打開(kāi)窗口的順序存儲(chǔ)窗口對(duì)象买置!
print( '所有窗口對(duì)象:', driver.window_handles ) 
print( '當(dāng)前窗口對(duì)象:', driver.current_window_handle )

# 切換窗口:
# 注意:窗口對(duì)象必須在相應(yīng)的頁(yè)面粪糙,driver才能操作對(duì)應(yīng)的頁(yè)面。
# 從窗口對(duì)象列表中索引出需要切換的窗口對(duì)象忿项,傳入即可蓉冈。
driver.switch_to.window( driver.window_handles[1] )
print( '當(dāng)前url:', driver.current_url )
print( '當(dāng)前窗口對(duì)象:', driver.current_window_handle )

(七)城舞、切換子網(wǎng)頁(yè)iframe:switch_to.frame

在網(wǎng)頁(yè)中可能嵌套著子網(wǎng)頁(yè),父網(wǎng)頁(yè)和子網(wǎng)頁(yè)是相對(duì)獨(dú)立的洒擦,查找某個(gè)網(wǎng)頁(yè)的元素必須切換到相應(yīng)網(wǎng)頁(yè)中才能找到椿争!
比如:如果在父網(wǎng)頁(yè)中查找子網(wǎng)頁(yè)的元素,則必須切換到子網(wǎng)頁(yè)熟嫩,否則找不到秦踪,反之亦然。
示例代碼

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
url = 'https://graph.qq.com/oauth2.0/show?which=Login&display=pc&client_id=100290348&response_type=code&state=ab183433jKFQqXF6b25lX3Nuc6FToKFO2UxodHRwczovL3Nzby50b3V0aWFvLmNvbS9hdXRoL2xvZ2luX3N1Y2Nlc3MvP3NlcnZpY2U9aHR0cHM6Ly93d3cudG91dGlhby5jb20voVYBoUkAoUQAoUEYoU0YoUivd3d3LnRvdXRpYW8uY29toVIEolBMAKZBQ1RJT06g&redirect_uri=http%3A%2F%2Fapi.snssdk.com%2Fauth%2Flogin_success%2F&scope=get_user_info,add_share,add_t,add_pic_t,get_info,get_other_info,get_fanslist,get_idollist,add_idol,get_repost_list'
driver.get(url) 

# 切換到主網(wǎng)頁(yè)(默認(rèn)iframe)
driver.switch_to.default_content()

# 多個(gè)iframe掸茅,切換到子網(wǎng)頁(yè)
driver.switch_to.frame("ptlogin_iframe")

# 注意:返回的子網(wǎng)頁(yè)的HTML代碼,而不是整個(gè)頁(yè)面
print( driver.page_source )  
# 點(diǎn)擊賬號(hào)密碼登錄
driver.find_element_by_id("switcher_plogin").click()

切換到當(dāng)前網(wǎng)頁(yè)的父網(wǎng)頁(yè)
driver.switch_to.parent_frame()

注意:切換子網(wǎng)頁(yè)有三種方式:

  • 根據(jù)iframe標(biāo)簽的name屬性值切換:driver.switch_to.frame('frame_name')
  • 根據(jù)多個(gè)子網(wǎng)頁(yè)frame的順序編號(hào)切換:driver.switch_to.frame(1)
  • 找到所有的iframe標(biāo)簽,然后通過(guò)索引切換到對(duì)應(yīng)子網(wǎng)頁(yè)driver.switch_to.frame( driver.find_elements_by_tag_name("iframe")[1] )

(八)椅邓、執(zhí)行JavaScript代碼:execute_script

有些動(dòng)作可能selenium沒(méi)有提供api,比如進(jìn)度條下拉昧狮、打開(kāi)新的窗口等景馁,這時(shí)我們可以通過(guò)代碼執(zhí)行JavaScript執(zhí)行相應(yīng)操作。

from selenium import webdriver
driver= webdriver.Chrome()
driver.get('https://www.zhihu.com/explore')

#進(jìn)度條滾動(dòng)到底
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
#彈出警告框
driver.execute_script('alert("To Bottom")')
#打開(kāi)一個(gè)新的窗口
driver.execute_script('window.open()')

(九)逗鸣、在selenium中設(shè)置代理

無(wú)認(rèn)證代理:

from selenium import webdriver

 #設(shè)置瀏覽器選項(xiàng)
options = webdriver.ChromeOptions() 
#設(shè)置無(wú)驗(yàn)證代理
options.add_argument('--proxy-server=https://106.75.226.36:808')   

driver = webdriver.Chrome( chrome_options=options )
driver.get("https://httpbin.org/ip")
print(driver.page_source)

認(rèn)證代理:

# 生成Chrome瀏覽器的代理認(rèn)證插件
import string
import zipfile

def create_proxyauth_extension(proxy_host, proxy_port,
                               proxy_username, proxy_password,
                               scheme='http', plugin_path=None):

    """代理認(rèn)證插件

    args:
        proxy_host (str): 你的代理地址或者域名(str類(lèi)型)
        proxy_port (int): 代理端口號(hào)(int類(lèi)型)
        proxy_username (str):用戶名(字符串)
        proxy_password (str): 密碼 (字符串)
    kwargs:
        scheme (str): 代理方式 默認(rèn)http
        plugin_path (str): 擴(kuò)展的絕對(duì)路徑

    return str -> plugin_path
    """

    import string
    import zipfile

    if plugin_path is None:
        plugin_path = 'vimm_chrome_proxyauth_plugin.zip'

    manifest_json = """
    {
        "version": "1.0.0",
        "manifest_version": 2,
        "name": "Chrome Proxy",
        "permissions": [
            "proxy",
            "tabs",
            "unlimitedStorage",
            "storage",
            "<all_urls>",
            "webRequest",
            "webRequestBlocking"
        ],
        "background": {
            "scripts": ["background.js"]
        },
        "minimum_chrome_version":"22.0.0"
    }
    """

    background_js = string.Template(
        """
        var config = {
                mode: "fixed_servers",
                rules: {
                  singleProxy: {
                    scheme: "${scheme}",
                    host: "${host}",
                    port: parseInt(${port})
                  },
                  bypassList: ["foobar.com"]
                }
              };

        chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

        function callbackFn(details) {
            return {
                authCredentials: {
                    username: "${username}",
                    password: "${password}"
                }
            };
        }

        chrome.webRequest.onAuthRequired.addListener(
                    callbackFn,
                    {urls: ["<all_urls>"]},
                    ['blocking']
        );
        """
    ).substitute(
        host=proxy_host,
        port=proxy_port,
        username=proxy_username,
        password=proxy_password,
        scheme=scheme,
    )
    with zipfile.ZipFile(plugin_path, 'w') as zp:
        zp.writestr("manifest.json", manifest_json)
        zp.writestr("background.js", background_js)

    return plugin_path
if __name__ == '__main__':
    from selenium import webdriver

    proxyauth_plugin_path = create_proxyauth_extension(
        proxy_host="47.92.24.143",
        proxy_port=16817,
        proxy_username="dsc0206",
        proxy_password="ng1lgio8"
    )

    # 設(shè)置瀏覽器選項(xiàng)
    options = webdriver.ChromeOptions()
    #設(shè)置驗(yàn)證代理
    options.add_argument("--start-maximized")
    options.add_extension(proxyauth_plugin_path)

    driver = webdriver.Chrome(chrome_options=options)
    driver.get("https://httpbin.org/ip")
    print(driver.page_source)

(十)合住、WebElement類(lèi)

from selenium.webdriver.remote.webelement import WebElement

獲取的元素logo、input是WebElement類(lèi)的實(shí)例對(duì)象撒璧;而driver則是WebDriver類(lèi)的對(duì)象透葛,但WebDriver類(lèi)繼承了WebElement類(lèi)。所以二者有很多相同屬性卿樱!(詳情見(jiàn)源碼)

可以將driver理解為BS4的BeautifulSoup對(duì)象(根節(jié)點(diǎn))僚害;將獲取的logo、input元素理解為BS4的tag對(duì)象(節(jié)點(diǎn))繁调。

from selenium import webdriver
driver = webdriver.Chrome()
print( type(driver ) )

driver.get(url='https://www.zhihu.com/explore')

#獲取網(wǎng)站logo萨蚕。
logo = driver.find_element_by_id('zh-top-link-logo')  
print('元素', logo)
print( '元素類(lèi)型', type(logo) )
print('元素屬性', logo.get_attribute('class'))   #獲取元素class屬性

input = driver.find_element_by_class_name('zu-top-add-question')
print('元素文本', input.text)  #獲取元素文本值
print('元素ID', input.id)  #獲取元素id
print('元素標(biāo)簽名', input.tag_name)   #獲取元素標(biāo)簽名
print('元素大小', input.size)   #獲取元素大小

driver.save_screenshot('知乎.png')   #截屏
driver.close()  #關(guān)閉當(dāng)前頁(yè)面
driver.quit()  #關(guān)閉瀏覽器

注意:雖然通過(guò)driver對(duì)象也可以解析HTML文檔,獲取信息蹄胰,但是不建議這樣做岳遥,效率低;使用driver對(duì)象獲取整個(gè)網(wǎng)頁(yè)的HTML代碼烤送,再使用lxml庫(kù)+xpath進(jìn)行解析寒随,效率高。


(十一)帮坚、Chrome的Headless模式(無(wú)界面模式)

Selenium運(yùn)行時(shí)妻往,必須要啟動(dòng)瀏覽器,瀏覽器的啟動(dòng)與關(guān)閉必然會(huì)影響執(zhí)行效率试和,而Chrome-headless 模式則可以不打開(kāi)瀏覽器UI界面的情況下使用 Chrome 瀏覽器讯泣。

代碼示例

from selenium import webdriver

# 設(shè)置瀏覽器選項(xiàng)
options= webdriver.ChromeOptions()

# 把chrome設(shè)置成無(wú)界面模式
options.add_argument('--headless')

driver = webdriver.Chrome(chrome_options=options)
driver.get('https://baidu.com/')
driver.save_screenshot('baidu.png')   #截屏

(十二)、操作瀏覽器的前進(jìn)與后退

代碼示例

import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
time.sleep(1)
browser.get('https://www.taobao.com/')

time.sleep(1)
browser.back()   #后退

time.sleep(1)
browser.forward()   #前進(jìn)

browser.close()

(十三)阅悍、selenium的異常處理

常用異常
TimeoutException:超時(shí)
NoSuchElementException:找不到元素
NoSuchAttributeException:元素的屬性找不到
NoSuchFrameException:要切換的子網(wǎng)頁(yè)不存在
NoSuchWindowException:要切換的窗口不存在
WebDriverException:WebDriver異常的基類(lèi)

代碼示例

from selenium import webdriver
from selenium.common.exceptions import TimeoutException  #超時(shí)異常
from selenium.common.exceptions import NoSuchElementException  #找不到元素異常

browser = webdriver.Chrome()

try:
    browser.get('https://www.baidu.com')
except TimeoutException:
    print('Time Out')

try:
    browser.find_element_by_id('hello')
except NoSuchElementException:
    print('No Element')
finally:
    browser.close()

參考文獻(xiàn):

Selenium官方文檔
Selenium用法詳解
Selenium 配置代理
Chrome的headless模式
selenium的常見(jiàn)異常


  1. 因?yàn)樵谝郧皞鬏敂?shù)據(jù)格式使用的是XML,因此叫做AJAX,而現(xiàn)在數(shù)據(jù)交換基本上都是使用JSON(故現(xiàn)在應(yīng)該叫做AJAJ才更合適)好渠。 ?

  2. AJAX技術(shù)只是動(dòng)態(tài)渲染網(wǎng)頁(yè)最常見(jiàn)的一種昨稼,還有采用其他方式的動(dòng)態(tài)渲染網(wǎng)頁(yè)。 ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拳锚,一起剝皮案震驚了整個(gè)濱河市假栓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌霍掺,老刑警劉巖匾荆,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異杆烁,居然都是意外死亡牙丽,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)兔魂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)烤芦,“玉大人,你說(shuō)我怎么就攤上這事析校」孤蓿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵智玻,是天一觀的道長(zhǎng)绰播。 經(jīng)常有香客問(wèn)我,道長(zhǎng)尚困,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任链蕊,我火速辦了婚禮事甜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘滔韵。我一直安慰自己逻谦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布陪蜻。 她就那樣靜靜地躺著邦马,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宴卖。 梳的紋絲不亂的頭發(fā)上滋将,一...
    開(kāi)封第一講書(shū)人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音症昏,去河邊找鬼随闽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛肝谭,可吹牛的內(nèi)容都是我干的掘宪。 我是一名探鬼主播蛾扇,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼魏滚!你這毒婦竟也來(lái)了镀首?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鼠次,失蹤者是張志新(化名)和其女友劉穎更哄,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體须眷,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡竖瘾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了花颗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捕传。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖扩劝,靈堂內(nèi)的尸體忽然破棺而出庸论,到底是詐尸還是另有隱情,我是刑警寧澤棒呛,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布聂示,位于F島的核電站,受9級(jí)特大地震影響簇秒,放射性物質(zhì)發(fā)生泄漏鱼喉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一趋观、第九天 我趴在偏房一處隱蔽的房頂上張望扛禽。 院中可真熱鬧,春花似錦皱坛、人聲如沸编曼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)掐场。三九已至,卻和暖如春贩猎,著一層夾襖步出監(jiān)牢的瞬間熊户,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工吭服, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留敏弃,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓噪馏,卻偏偏與公主長(zhǎng)得像麦到,于是被迫代替她去往敵國(guó)和親绿饵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容