「Python爬蟲系列講解」八、Selenium 技術

本專欄是以楊秀璋老師爬蟲著作《Python網絡數據爬取及分析「從入門到精通」》爲主線、個人學習理解爲主要內容,以學習筆記形式編寫的。
本專欄不光是自己的一個學習分享,也希望能給您普及一些關於爬蟲的相關知識以及提供一些微不足道的爬蟲思路。
專欄地址:Python網絡數據爬取及分析「從入門到精通」
更多爬蟲實例詳見專欄:Python爬蟲牛刀小試

前文回顧:
「Python爬蟲系列講解」一、網絡數據爬取概述
「Python爬蟲系列講解」二、Python知識初學 
「Python爬蟲系列講解」三、正則表達式爬蟲之牛刀小試 
「Python爬蟲系列講解」四、BeautifulSoup 技術
「Python爬蟲系列講解」五、用 BeautifulSoup 爬取電影信息
「Python爬蟲系列講解」六、Python 數據庫知識
「Python爬蟲系列講解」七、基於數據庫存儲的 BeautifulSoup 招聘爬取


目錄

 1 初識 Selenium

1.1 安裝 Selenium

1.2 安裝瀏覽器驅動

1.3 PhantomJS

2 快速開始 Selenium 解析

3 定位元素

3.1 通過 id 屬性定位元素

3.2 通過 name 屬性定位元素

3.3 通過 XPath 路徑定位元素

3.4 通過超鏈接文本定位元素

3.5 通過標籤名定位元素

3.6 通過類名定位元素

3.7 通過 CSS 選擇器定位元素

4 常用方法和屬性

4.1 操作元素的方法

4.2 WebElement 常用屬性

5 鍵盤和鼠標自動化操作

5.1 鍵盤操作

5.2 鼠標操作

6 導航控制

6.1 下拉菜單交互操作

6.2 Window 和 Frame 間對話框的移動

7 本文小結

 


Selenium 是一款用於測試 Web 應用程序的經典工具,它直接運行在瀏覽器中,彷彿真正的用戶在操作瀏覽器一樣,主要用於網站自動化測試、網站模擬登陸、自動操作鍵盤和鼠標、測試瀏覽器兼容性、測試網站功能等,同時也可以用於製作簡易的網絡爬蟲。

本文主要介紹 Selenium Python API 技術,它以一種非常直觀的方式來訪問 Selenium WebDriver 的所有功能,包括定位元素、自動操作鍵盤鼠標、提交頁面表單、抓取所需信息等。

 1 初識 Selenium

Selenium 是 Thought Work 公司專門爲 Web 應用程序編寫的一個驗收測試工具,它提供的 API 支持多種語言,包括  Python、Java、C# 等,本文主要介紹 Python 環境下的 Selenium 技術。Python 語言提供了 Selenium 擴展庫,它是使用 Selenium WebDriver(網頁驅動)來編寫功能、驗證測試的一個 API 接口。通過 Selenium Python API,用戶可以以一種直觀的方式來訪問 Selenium WebDriver 的所有功能。Selenium Python 支持多種瀏覽器,諸如 Chrome、火狐、IE、360 等,也支持 PhantomJS 特殊的無界面瀏覽器引擎。

類似於前幾期文章講到的 BeautifulSoup 技術,Selenium 製作的爬蟲也是先分析網頁的 HTML 源碼和 DOM 樹結構,在通過其所提供的方法定位到所需信息的節點位置,並獲取其文本內容。

1.1 安裝 Selenium

pip install selenium

Selenium 安裝成功之後,接下來需要調用瀏覽器進行定位或爬取信息,而使用瀏覽器時需要先安裝瀏覽器驅動。下面介紹瀏覽器驅動的配置過程。

1.2 安裝瀏覽器驅動

首先,下載瀏覽器驅動器WebDriver

chrom瀏覽器的驅動器下載地址:http://npm.taobao.org/mirrors/chromedriver/

firefox(火狐瀏覽器)的驅動器下載地址:https://github.com/mozilla/geckodriver/releases

Edge瀏覽器的驅動器下載地址:https://developer.microsoft.com/en-us/micrsosft-edage/tools/webdriver

Safari瀏覽器的驅動器下載地址:https://webkit.org/blog/6900/webdriver-support-in-safari-10/

以谷歌瀏覽器爲例,需要首先知道瀏覽器的版本號

只需要前面的83.0對應好就OK,大的方向對應了就行,然後找到相匹配的版本進行下載 

安裝好之後,進入測試環節,下面給出加載主流瀏覽器驅動的核心代碼:

①Firefox 瀏覽器

from selenium import webdriver
driver = webdriver.Firefox()
driver.get('http://www.baidu.com')

②Chrom 瀏覽器(需要指定瀏覽器驅動的本地目錄地址)

import os
from selenium import webdriver
chromedriver = 'E:/software/chromedriver_win32/chromedriver.exe'
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
driver.get('http://www.baidu.com')

③IE 瀏覽器

from selenium import webdriver
driver = webdriver.IE()
driver.get('http://www.baidu.com')

1.3 PhantomJS

PhantomJS 是一個服務器端的 JavaScript API 的開源瀏覽器引擎(WebKit),它支持各種 Web 標準,包括 DOM 樹分析、CSS 選擇器、JSON 和 SVG 等。PhantomJS 常用於頁面自動化、網絡監測、網頁截屏以及無界面測試等。

下載地址:https://phantomjs.org/download.html

建議直接下載並解壓至 Scripts 目錄環境下,如下圖所示:

當 Selenium 安裝成功且 PhantomJS 下載並配置好之後,其調用方法如下: 

# 導入 Selenium.webdriver 擴產庫,並提供了 webdriver 實現方法
from selenium import webdriver
# 創建 driv 實例,調用 webdriver.PhantomJS 方法配置路徑
driver = webdriver.PhantomJS(executable_path="E:\software\python3.8.2\Scripts\phantomjs-2.1.1-windows\phantomjs.exe")
# 打開百度網頁,webdriver 會等待網頁元素加載完成之後才能把控制權交回腳本
driver.get('http://www.baidu.com')
# 獲取文章標題並賦值給 data 變量輸出
data = driver.title
# data 變量值爲“百度一下,你就知道”
print(data)

:webdriver 中提供的 save_screenshot() 函數可以對網頁進行截圖。

2 快速開始 Selenium 解析

網頁通常採用文檔對象模型樹結構進行存儲,並且這些節點都是成對出現的,如 “<html>” 對應 “</html>”、“<table>” 對應 “</table>”等。Selenium 技術通過定位節點的特定屬性,如 class、id、name 等,可以確定當前節點的位置,然後再獲取相關網頁的信息。

如下代碼實現的功能是定位百度搜索框並進行自動搜索,可以將其作爲我們快速入門的代碼。

import time
import os
from selenium import webdriver
from selenium.webdriver.common.keys import Keys   # 該 Keys 類提供了操作鍵盤的快捷鍵,如空格鍵、回車鍵等

# 瀏覽驅動器路徑
chromedriver = 'E:/software/chromedriver_win32/chromedriver.exe'
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
# 打開網頁
driver.get('http://www.baidu.com')
# 使用斷言(assert)判斷文章標題是否包含“百度”字段。若不包括則報錯,若包括則繼續執行下一條語句
assert "百度" in driver.title
# 查找元素定位百度搜索輸入文本框(見上圖)
elem = driver.find_element_by_name("wd")
# 模擬鍵盤操作,輸入“CSDN”字段
elem.send_keys("CSDN")
# 輸入回車鍵進行操作
elem.send_keys(Keys.RETURN)

time.sleep(10)
# 進行截圖操作
driver.save_screenshot('baidu.png')
# 關閉驅動
driver.close()  # 關閉頁面
# 退出驅動
driver.quit()   # 退出瀏覽器

3 定位元素

Selenium Python 提供了一種用於定位元素(Locate Element)的策略,用戶可以根據所爬取網頁的 HTML 結構選擇最合適的方案。當定位多個元素時,只需將方法 “element” 加 “s” ,這些元素將會以一個列表的形式返回。

Selenium 元素定位的方法
定位單個元素的方法 定位多個元素的方法 方法的含義
find_element_by_id find_elements_by_id 通過 id 屬性定位元素
find_element_by_name find_elements_by_name 通過 name 屬性定位元素
find_element_by_xpath find_elements_by_xpath 通過 XPath 路徑定位元素
find_element_by_link_text find_elements_by_link_text 通過顯示文本定位元素
find_element_by_partial_link_text find_elements_by_partial_link_text 通過超鏈接文本定位元素
find_element_by_tag_name find_elements_by_tag_name 通過標籤名定位元素
find_element_by_class_name find_elements_by_class_name 通過類屬性名定位元素
find_element_by_css_selector find_elements_by_css_selector 通過CSS選擇器定位元素

本文將結合下面的 HTML 代碼分別介紹各種元素的定位方法,並以定位單位元素爲主。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李白簡介</title>
</head>
<body>
<p class="title"><b>靜夜思</b></p>
<p class="content">
    牀前明月光,<br/>
    疑是地上霜。<br/>
    舉頭望明月,<br/>
    低頭思故鄉。<br/>
</p>
<div class="other" align="left" name="di" id="nr">
    李白(701年-762年) ,字太白,號青蓮居士,又號“謫仙人”,
    唐代偉大的浪漫主義詩人,被後人譽爲“詩仙”,與
    <a href="https://baike.baidu.com/item/%E6%9D%9C%E7%94%AB/63508" class="poet" id="link" name="dufu">杜甫</a>
    並稱爲“李杜”,爲了與另兩位詩人
    <a href="https://baike.baidu.com/item/%E6%9D%8E%E5%95%86%E9%9A%90/74852" class="poet" id="link" name="lsy">李商隱</a>
    與<a href="https://baike.baidu.com/item/%E6%9D%9C%E7%89%A7" class="poet" id="link" name="dumu">杜牧</a>
    即“小李杜”區別,杜甫與李白又合稱“大李杜”。
    據《新唐書》記載,李白爲興聖皇帝(涼武昭王李暠)九世孫,與李唐諸王同宗。
    其人爽朗大方,愛飲酒作詩,喜交友。
</div>
<p class="story">……</p>
</body>
</html>

3.1 通過 id 屬性定位元素

該方法通過網頁標籤的 id 屬性來定位元素,它將返回第一個與 id 屬性值匹配的元素。如果沒有元素與 id 值匹配,則返回一個 NoSuchElementException 異常。

現在假設需要通過 id 屬性定位頁面中的 “杜甫”、“李商隱”、“杜牧” 3 個超鏈接,則 HTML 核心代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李白簡介</title>
</head>
<body>
   ...
<div class="other" align="left" name="di" id="nr">
    李白(701年-762年) ,字太白,號青蓮居士,又號“謫仙人”,
    唐代偉大的浪漫主義詩人,被後人譽爲“詩仙”,與
    <a href="https://baike.baidu.com/item/%E6%9D%9C%E7%94%AB/63508" class="poet" id="link" name="dufu">杜甫</a>
    並稱爲“李杜”,爲了與另兩位詩人
    <a href="https://baike.baidu.com/item/%E6%9D%8E%E5%95%86%E9%9A%90/74852" class="poet" id="link" name="lsy">李商隱</a>
    與<a href="https://baike.baidu.com/item/%E6%9D%9C%E7%89%A7" class="poet" id="link" name="dumu">杜牧</a>
    即“小李杜”區別,杜甫與李白又合稱“大李杜”。
    據《新唐書》記載,李白爲興聖皇帝(涼武昭王李暠)九世孫,與李唐諸王同宗。
    其人爽朗大方,愛飲酒作詩,喜交友。
</div>
   ...
</body>
</html>

 

如果需要獲取 div 佈局,則使用如下代碼:

import os
from selenium import webdriver

# 瀏覽驅動器路徑
chromedriver = 'E:/software/chromedriver_win32/chromedriver.exe'
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
# 打開 HTML 本地網頁
driver.get('http://localhost:63342/PycharmProjects/test_poetry.html?_ijt=fu8obkjef7c2i45o7qjji407mk')

test_div = driver.find_element_by_id('nr')
print(test_div.text)

 如果寫成如下代碼(展示核心代碼),則返回第一個詩人的信息:

test_poet = driver.find_element_by_id('link')
print(test_poet.text)

 如果想要通過 id 屬性獲取多個鏈接,比如 “杜甫”、“李商隱”、“杜牧” 3 個超鏈接,則需使用 find_elements_by_id() 函數,注意 “elements” 表示獲取多個值。3 個超鏈接都是用同一個 id 名稱 “link”,通過 find_elements_by_id() 函數定位獲取之後,再調用 for 循環輸出結果,如下(展示核心代碼):

test_div = driver.find_elements_by_id('link')
for t in test_div:
    print(t.text)

3.2 通過 name 屬性定位元素

該方法通過網頁標籤的 name 屬性來定位元素,它將返回第一個與 name 屬性值匹配的元素。如果沒有元素與 name 值匹配,則返回一個 NoSuchElementException 異常。

下面介紹通過 name 屬性來定位頁面中 “杜甫”、“李商隱”、“杜牧” 3 個超鏈接的方法,HTML 源碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李白簡介</title>
</head>
<body>
   ...
<div class="other" align="left" name="di" id="nr">
    ...
    <a href="https://baike.baidu.com/item/%E6%9D%9C%E7%94%AB/63508" class="poet" id="link" name="dufu">杜甫</a>
    ...
    <a href="https://baike.baidu.com/item/%E6%9D%8E%E5%95%86%E9%9A%90/74852" class="poet" id="link" name="lsy">李商隱</a>
    與<a href="https://baike.baidu.com/item/%E6%9D%9C%E7%89%A7" class="poet" id="link" name="dumu">杜牧</a>
    ...
</div>
   ...
</body>
</html>

如果需要分別捕獲  “杜甫”、“李商隱”、“杜牧” 3 個超鏈接,則相應代碼如下:

test_poet1 = driver.find_element_by_name('dufu')
test_poet2 = driver.find_element_by_name('lsy')
test_poet3 = driver.find_element_by_name('dumu')
print(test_poet1, test_poet2, test_poet3)

值得注意的是,test_poet 是獲取的值,通常爲 “<selenium.webdriver.remote.webelement.WebElement (session="6a99b53764fff729043db6aa1f4db1d9", element="d860b63e-bcb6-4d75-825c-47b4a538883d")> ” ,而 text 是獲取其文本內容,即返回  “杜甫”、“李商隱”、“杜牧” 3 個值。

值得注意的還有,此時不能調用 find_elements_by_name() 函數來獲取多個元素,因爲 3 個人物超鏈接的 name 屬性是不同的。 

3.3 通過 XPath 路徑定位元素

XPath 是用於定位 XML 文檔中節點的技術,HTML/XML 都是採用網頁 DOM 樹狀標籤的結構進行編寫的,所以可以通過 XPath 方法分析其節點信息。Selenium Python 也提供了類似的方法來跟蹤網頁中的元素。

XPath 路徑定位元素方法不同於按照 id 或 name 屬性的定位方法,前者更加的靈活、方便。比如,想通過 id 屬性定位第三位詩人“杜牧”的超鏈接信息,但是 3 位詩人的 id 屬性都是 link,如果沒有其他屬性,那將如何實現呢?此時可以藉助 XPath 方法進行定位。這也體現了 XPath 方法的一個優點,即當沒有一個合適的 id 或 name 屬性來定位所需要查找的元素時,可以使用 XPath 去定位這個絕對元素(但不建議定位絕對元素),或者定位一個有 id 或 name 屬性的相對元素位置。

XPath 方法也可以通過除了 id 和 name 屬性的相對元素進行定位,其完整函數爲 find_element_by_xpath() 和  find_elements_by_xpath()。

下面開始通過實例進行講解,HTML 代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李白簡介</title>
</head>
<body>
<p class="title"><b>靜夜思</b></p>
<p class="content">
    牀前明月光,<br/>
    疑是地上霜。<br/>
    舉頭望明月,<br/>
    低頭思故鄉。<br/>
</p>
<div class="other" align="left" name="di" id="nr">
    李白(701年-762年) ,字太白,號青蓮居士,又號“謫仙人”,
    唐代偉大的浪漫主義詩人,被後人譽爲“詩仙”,與
    <a href="https://baike.baidu.com/item/%E6%9D%9C%E7%94%AB/63508" class="poet" id="link" name="dufu">杜甫</a>
    並稱爲“李杜”,爲了與另兩位詩人
    <a href="https://baike.baidu.com/item/%E6%9D%8E%E5%95%86%E9%9A%90/74852" class="poet" id="link" name="lsy">李商隱</a>
    與<a href="https://baike.baidu.com/item/%E6%9D%9C%E7%89%A7" class="poet" id="link" name="dumu">杜牧</a>
    即“小李杜”區別,杜甫與李白又合稱“大李杜”。
    據《新唐書》記載,李白爲興聖皇帝(涼武昭王李暠)九世孫,與李唐諸王同宗。
    其人爽朗大方,愛飲酒作詩,喜交友。
</div>
<p class="story">……</p>
</body>
</html>

上述 div 佈局可以通過以下 3 中 XPath 方法定位:

# 方法一:使用絕對路徑定位,從HTML代碼的根節點開始定位元素,但如果HTML代碼稍有改動,其結果就會被破壞
test_div1 = driver.find_element_by_xpath("/html/body/div[1]")
# 方法二:獲取 HTML 代碼中的第一個 div 佈局元素。如果 div節點位置太深,則需尋找附近一個元素的 id 或 name 屬性進行定位
test_div2 = driver.find_element_by_xpath("//div[1]")
# 方法三:定位 id 屬性值爲”nr“的 div 佈局元素,此時可以定位介紹三位詩人的簡介信息。
test_div3 = driver.find_element_by_xpath("//div[@id='nr']")
print(test_div1.text, test_div2.text, test_div3.text)

# 方法一:定位 div 節點下的一個超鏈接 a 元素,且 a 元素,且 a 元素 name 屬性爲 “dumu”
test_div1 = driver.find_element_by_xpath("//div[a/@name='dumu']")
# 方法二:定位“id='nr'”的元素,再找到它的第三個超鏈接 a 子元素
test_div2 = driver.find_element_by_xpath("//div[@id='nr']/a[3]")
# 方法三:定位 name 屬性爲 “杜牧” 的第一個超鏈接
test_div3 = driver.find_element_by_xpath("//a[@name='dumu']")
print(test_div2.text, test_div3.text)

如果是按鈕控件並且其 name 屬性相同,假設 HTML 代碼如下:

<form id='loginForm'>
    <input name="continue" type="submit" value="Login"/>
    <input name="continue" type="submit" value="Clear"/>
</form>

 則定位 value 值爲 “Clear” 按鈕元素的方法如下:

# 定位屬性 name 爲 “continue” 且屬性 type 爲“button” 的 input 控件
clearb = driver.find_element_by_xpath("//input[@name='continue'][@type='button']")
# 定位屬性“id=loginForm”的form節點下的第二個 input 子元素
clearb = driver.find_element_by_xpath("//form[@id='loginForm']/input[2]")

3.4 通過超鏈接文本定位元素

當需要定位一個錨點標籤內的鏈接文本(Link Text)時可以通過超鏈接文本定位元素的方法進行定位。該方法返回第一個匹配該鏈接文本值的元素。如果沒有元素與該鏈接文本匹配,則拋出一個 NoSuchElementException 異常。

下面將介紹如何通過該方法來定位頁面中“杜甫”“李商隱”“杜牧”這 3 個超鏈接,HTML 源碼如下:

<!DOCTYPE html>
<html>
<body>
<div class="other" align="left" name="d1" id="nr">
    <a href="dufu.html" class="poet" id="link" name="dufu">DF</a>
    <a href="lsy.html" class="poet" id="link" name="lsy">LSY</a>
    <a href="dumu.html" class="poet" id="link" name="dumu">DM</a>
</div>
</body>
</html>

則分別獲取“杜甫”、“李商隱”、“杜牧” 3 個超鏈接的代碼如下:

# 分別定位 3 個超鏈接
test_poet1 = driver.find_element_by_link_text('DF')
test_poet2 = driver.find_element_by_link_text('LSY')
test_poet3 = driver.find_element_by_link_text('DM')
print(test_poet1.text, test_poet2.text, test_poet3.text)

# 定位超鏈接部分元素
test_poet4 = driver.find_element_by_partial_link_text('D')
print(test_poet4.text)

# 定位超鏈接部分元素且定位多個元素
test_poet5 = driver.find_elements_by_partial_link_text('D')
for t in test_poet5:
    print(t.text)

注: find_element_by_link_text() 函數使用錨點標籤的鏈接文本進行定位;
        driver.find_elements_by_partial_link_text() 函數可以獲取多個元素。

3.5 通過標籤名定位元素

通過標籤名(Tag Name)定位元素並將返回第一個用標籤名匹配定位的元素。如果沒有元素匹配,則拋出一個 NoSuchElementException 異常。

假設 HTML 源碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李白簡介</title>
</head>
<body>
<h1>靜夜思</h1>
<p class="conterot">牀前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。</p>
</body>
</html>

定位元素 h1 和段落 p 的方法如下:

test1 = driver.find_element_by_tag_name('h1')
test2 = driver.find_element_by_tag_name('p')
print(test1.text, test2.text)

3.6 通過類名定位元素

通過類屬性名(Class Attribute Name)定位元素將返回第一個用類屬性名匹配定位的元素。如果沒有元素匹配,則返回一個 NoSuchElementException 異常。

通過 class 屬性值定位段落 p 元素的方法如下:

test1 = driver.find_element_by_class_name('content')

3.7 通過 CSS 選擇器定位元素

通過 CSS 選擇器(CSS Selector)定位元素將返回第一個與 CSS 選擇器匹配的元素。如果沒有元素匹配,則返回一個 NoSuchElementException 異常。

通過 CSS 選擇器定位段落 p 元素的方法如下:

test1 = driver.find_element_by_css_selector('p.content')

如果存在多個相同的 class 屬性值的 content 標籤,則可以使用下面的方法進行定位:

test1 = driver.find_element_by_css_selector(*.content)
test2 = driver.find_element_by_css_selector(.content)

通過 CSS 選擇器定位元素的方法是比較難的一個方法,相比較而言,使用 id、name 和 XPath 等常用的定位元素方法更加實用。

4 常用方法和屬性

4.1 操作元素的方法

定位操作完成後需要對已經定位的對象進行操作,這些操作的頁面行爲通常需要通過 WebElement 接口實現。

常見操作元素的方法
方法 含義
clear() 清除元素的內容
send_keys(key) 模擬鍵盤按鍵操作,輸入關鍵字(key)
click() 單擊元素
submit() 提交表單
get_attribute() 獲取屬性爲 name 的屬性值
is_displayed() 設置該元素是否可見
is_enabled() 判斷元素是否被使用
is_selected() 判斷元素是否被選中

下面舉一個自動登錄百度首頁的示例,利用該示例來講解常見操作元素的方法。

 
通過上圖所示方法可以看到百度首頁“登錄”按鈕對應的 HTML 源碼。 

首先用瀏覽器驅動打開目標網頁

# 瀏覽驅動器路徑
chromedriver = 'E:/software/chromedriver_win32/chromedriver.exe'
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
# 打開網頁
driver.get('https://www.baidu.com/?tn=78040160_5_pg&ch=8')

通過 name 值爲 “ tj_login ” 鎖定並單擊 “登錄” 按鈕,跳轉至登錄頁面

login = driver.find_element_by_name("tj_login")
login.click()

通過 id 值查找 “用戶名登錄” 並單擊它。

denglu = driver.find_element_by_id('TANGRAM__PSP_11__footerULoginBtn')

 

根據上圖,用同樣的方法定位輸入框並清除默認數據後輸入賬戶密碼,單擊登錄。

name = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_11__userName"]')
name.send_keys("這裏填賬戶")
pwd = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_11__password"]')
pwd.send_keys("這裏填密碼")
denglu = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_11__submit"]')
denglu.click()

下面給出完整代碼參考:

import time
import os
from selenium import webdriver

# 瀏覽驅動器路徑
chromedriver = 'E:/software/chromedriver_win32/chromedriver.exe'
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
# 打開網頁
driver.get('https://www.baidu.com/?tn=78040160_5_pg&ch=8')

# 登錄按鈕
login = driver.find_element_by_xpath('//*[@id="u1"]/a[2]')
print(login.text)
login.click()
time.sleep(3)
# 切換賬號密碼登錄
dl = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_11__footerULoginBtn"]')
dl.click()
time.sleep(3)
# 填入賬號密碼
name = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_11__userName"]')
name.send_keys("這裏填賬戶")
time.sleep(1)
pwd = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_11__password"]')
pwd.send_keys("這裏填密碼")
time.sleep(1)
# 點擊登錄按鈕
denglu = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_11__submit"]')
denglu.click()

 

:每步加載需要時間,故設置適當的 sleep 值使得程序順利執行、不易報錯。 

4.2 WebElement 常用屬性

通過 WebElement 接口可以獲取常用的值。

常見屬性值
方法 含義
size 獲取元素的尺寸
text 獲取元素的文本
location 獲取元素的座標,先找到要獲取的元素,再調用該方法
page_source 返回頁面源碼
title 返回頁面標題
current_url 獲取當前頁面的 URL
tag_name 返回元素的標籤名稱

5 鍵盤和鼠標自動化操作

Selenium 技術還可以實現自動操作鍵盤鼠標的功能,所以它更多地用用於自動化測試領域,通過自藕丁操作網頁、反饋響應的結果來檢測網站的健壯性和安全性。

5.1 鍵盤操作

常用鍵盤操作
方法 含義
send_keys(Key,ENTER) 按回車鍵,最常用按鍵操作
send_keys(Key,TAB) 按 Tab 鍵
send_keys(Key,SPACE) 按空格鍵
send_keys(Key,ESCAPE) 按 Esc 鍵
send_keys(Key,BACK_SPACE) 按 Backspace 鍵
send_keys(Key,SHIFT) 按 Shift 鍵
send_keys(Key,CONTROL) 按 Ctrl 鍵
send_keys(Key,CONTROL,'a') 按 Ctrl + A 快捷鍵全選
send_keys(Key,CONTROL,'c') 按 Ctrl + C 快捷鍵複製
send_keys(Key,CONTROL,'x') 按 Ctrl + X 快捷鍵剪切
send_keys(Key,CONTROL,'v') 按 Ctrl + V 快捷鍵粘貼

5.2 鼠標操作

常見鼠標操作
方法 含義
click() 單擊一次
context_click(elem) 右擊元素 elem,比如在彈出的快捷菜單中選擇“另存爲”等命令 
double_click(elem) 雙擊元素 elem
drag_and_drop(source,target) 鼠標拖動操作,在源元素 source 位置處按下鼠標左鍵並移動至目標元素 target,然後釋放
send_keys(Keys, BACK_SPACE) 按 Backspace 鍵
move_to_element(elem) 將光標移動到元素 elem 上
click_and_hold(elem) 按下鼠標左鍵並懸停在元素 elem 上
perform() 執行 ActionChains 類中的存儲操作,彈出對話框

6 導航控制

下面介紹 Selenium 的導航控制操作,包括頁面交互、表單操作和對話框間的移動等內容。

6.1 下拉菜單交互操作

前面講述的百度搜索案例就是一個頁面交互的過程,包括:

  • 調用 driver.find_element_by_xpath() 函數定位元素
  • 調用 send_keys(key) 輸入關鍵詞或鍵盤按鍵,如輸入 Keys.RETURN 回車鍵。
  • 調用 click() 函數單擊,執行另存爲圖片的操作等。

這裏將補充頁面交互切換下拉菜單的實例。定位 "name" 下拉菜單標籤後,調用 SELECT 類選中選項,同時 select_by_visible_text() 用於顯示選中的菜單,也可以提交 Form 表單,具體代碼如下:

from selenium.webdriver.support.ui import Select
name = driver.find_element_by_name("name")
select = Select(name)
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)

如果想取消已選中的選項,則可以使用如下代碼:

from selenium.webdriver.support.ui import Select
name = driver.find_element_by_name("name")
select = Select(name)
all_selected_options = select.all_selected_options

如果想獲取所有的可用選項,則可嗲用 select.options。當填寫完表單後,可以通過 submit() 函數提交,或者找到提交按鈕後調用 “ driver.find_element_by_id("submit").click*() ” 提交。

6.2 Window 和 Frame 間對話框的移動

網站通常都是由多個窗口組成的,稱爲多幀 Web 應用。webdriver 提供 switch_to_window() 方法來支持命名窗口間的移動切換,如下:

driver.switch_to_window("windowName")

現在 driver 的所有操作都將針對特定的窗口,因此可以通過定位其 HTML 源碼中的超鏈接,或者給 switch_to_window() 方法傳遞一個 “窗口句柄” 來實現。常用方法是,循環遍歷所有的窗口,獲取指定的句柄進行定位操作,核心代碼如下:

for handle in driver.window_handles:
    driver.switch_to_window(handle)

在幀與幀(Iframe)之間切換使用 “ driver.switch_to_frame("frameName") ” 函數。對於彈出式對話框,Selenium webdriver 提供了內建支持,switch_to_alert() 函數將返回當前打開的 alert 對象,通過該對象可以進行確認同意或反對操作,也可以讀取它的內容,代碼如下:

alert = driver.switch_to_alert()

 下面是捕獲彈出式對話框內容的核心代碼:

# 獲取當前窗口句柄
now_handle = driver.current_window_handle
print(now_handle)

# 獲取所有窗口句柄
all_handles = driver.window_handles
for handle in all_handles:
    if handle != now_handle:
        # 輸出待選擇的窗口句柄
        print(handle)
        driver.switch_to_window(handle)
        time.sleep(1)
        # 具體操作
        elem_bt = driver.find_element_by_xpath("...")
        driver.close()    # 關閉當前窗口

# 輸出主窗口句柄
print(now_handle)
driver.switch_to_window(now_handle)  # 返回主窗口

7 本文小結

Selenium 庫分析和定位節點的方法與 BeautifulSoup 庫類似,他們都能夠利用類似於 XPath 技術的方法來定位標籤,都擁有豐富的操作函數來爬取數據。但不同之處在於,Selenium 能方便地操控鍵盤、鼠標,以及切換對話框、提交表單等。對於目標網頁需要驗證登錄後才能爬取,所爬取的數據位於彈出對話框中或所爬取的數據通過超鏈接跳轉到了新的窗口等情況,Selenium 技術的優勢就體現出來了,它可以通過控制鼠標模擬登錄或提交表單來爬取數據,但其缺點是爬取效率較低。


歡迎留言,一起學習交流~

感謝閱讀

END

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章