2023年5月29日 星期一

爬蟲筆記-selenium初章

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

driver = webdriver.Chrome()
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element(By.NAME, "q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()

上面這段程式碼中

首先是匯入使用驅動程式的模塊

再來是模擬使用者輸入模塊

再者是定位元素模塊

selenium webdirver 模塊提供所有的WebDriver實現。目前之前的WebDriver實現的有

FireFox  、 Chrome 、 IE 和 Remmote 。


Keys類提供鍵盤中的按鍵操作 , 例如 RETURN (就是鍵盤的ENTER)、 F1 、ALT等。

By類用於定位文檔中的元素

接下來創建Chrome的實例

driver = webdriver.Chrome()  #確保Chrome驅動程式放在專案同一層資料夾

driver.get(url) #使用driver.get方法將透過導航到統一資源定位符給定的位置

正常情況下WebDriver將等到頁面完全加載(即onload 100%)再繼續執行,

但如果頁面使用了大量AJAX, 則 WebDriver可能不知他何時完全加載完畢

可以使用time等待頁面加載完成

assert 'Python' in driver.title   #斷言文本標題包含Python字串,

assert是可以幫助判斷頁面載入情況是否符合預期


<input id="id-search-field" name="q" type="search" role="textbox" class="search-field"

    placeholder="Search" value="" tabindex="1">

elem=driver.find_element(By.NAME,'q')  #定位文本元素中有name='q'的標籤

elem.clear()   #首先清除欄位中任何預設的填充文本,比方說搜索, #再輸入我們要搜尋的內容

elem.send_Keys("pycon")  #在定位的欄位中輸入"pycon"

elem.send_Keys(Keys.RETURN) #模擬鍵盤中的ENTER操作

#已知頁面的搜索結果是"No results found" 


assert "No results found." in driver.page_source  #斷言No results found存在網頁文本中

#但如果希望有結果的話 就改成assert "No results found." not in driver.page_source  ,引發ASSERTOINERROR ,中斷程式



driver.close() #關閉瀏覽器窗口,但quit方法比較好 quit()會關閉瀏覽器後完全釋放driver資源



與頁面進行交互

上面僅提到能夠使用自動化導航至某個地方,並沒有很實用,但我們可以透過搭配頁面的HTML元素進行更多操作。


<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_element(By.XPATH,"//input[@id='passwd-id']")
element=driver.find_element(By.CSS_SELECTOR,"input#passwd-id")

定位到元素之後我們可以對該元素進行操作

比方說傳入一些文本訊息

# 如果要在某個元素中傳入文本訊息的話,先清空該元素的任何預設文本
element.clear()
element.send_keys('some text')

#使用Keys類模擬使用者按下箭頭鍵
element.send_keys('and some',Keys.ARROW_DOWN)

#如果我們想在某個元素中傳入文本訊息的話, 就可以透過上面的element.send_keys('some text')

方法,但這個方法,他不會把元素中的預設文字清除,容易造成錯誤

所以我們要先使用element.clear() 清空該元素的任何預設文本

在使用element.send_keys('some text')

確保輸入的文字符合我們預期


填寫表格

#如果元素中遇到可以'切換'下拉列表的狀態,並且可以使用"setSelected"來設置諸如選擇OPTION標籤之類的內容。處理SELECT標籤還不錯







在窗口和框架之間移動

webdriver支持使用"switch_to.window"方法在命名窗口之間移動

driver.switch_to.window('Windowname')

所有對 的調用driver現在都將被解釋為定向到特定窗口,要查看窗口的名稱查看他的javascript或鏈接

<a href="somewhere.html" target="windowName">Click here to open a new window</a>

或者可以將窗口具柄傳遞給switch_to.window()方法,知道這點就可以像這樣便利每個打開的窗口

for handle in driver.window_handles:
    driver.switch_to.window(handle)

也可以從一個框架切換到另一個框架(或進入iframe)

driver.switch_to.frame('frameName')

可以通過用.來分隔路徑來訪問子幀,你也可以通過其索引指定幀。那是:

driver.switch_to.frame('franeName.0.child')

將轉到名為"frameName"的框架的第一個子框架的名為"child"的框架。所有幀都被評估為從

"top"開始

一旦我們完成了對框架的處理,我們將不得不回到父框架,這可以使用以下方法

driver.switch_to.default_content()


彈出對話框

Selenium WebDriver 內置了對處理彈出對話框的支持。在觸發會打開彈出窗口的操作後,可以通過以下方式訪問警報:
alert=driver.switch_to.alert


導航:歷史和位置

我們介紹過使用"get"命令()導航到頁面driver.get("url")

要在瀏覽器的歷史紀錄中前後移動:
driver.forward()
driver.back()

注意,這項功能決定在底層的驅動程序,不同驅動可能有不能的結果


 餅乾














定位元素


from selenium.webdriver.common.by import By

driver.find_element(By.XPATH, '//button[text()="Some text"]')
driver.find_elements(By.XPATH, '//button')

可用於By類的屬性用於定位頁面上的元素。這些是可用於按類的屬性

ID = "id"
NAME = "name"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"

'By' 類用於指定使用哪個屬性來定位頁面上的元素。這些是屬性用於在頁面上定位元素的各種方式:

find_element(By.ID, "id")
find_element(By.NAME, "name")
find_element(By.XPATH, "xpath")
find_element(By.LINK_TEXT, "link text")
find_element(By.PARTIAL_LINK_TEXT, "partial link text")
find_element(By.TAG_NAME, "tag name")
find_element(By.CLASS_NAME, "class name")
find_element(By.CSS_SELECTOR, "css selector")

如果要查找具有相同屬性的多個元素,請將 find_element 替換為 find_elements。


4.1. 通過 Id 定位

當您知道元素的id屬性時使用它。使用此策略,將返回具有匹配id屬性的第一個元素。如果沒有元素具有匹配的idNoSuchElementException屬性,將引發a 。

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
  </form>
 </body>
</html>

這個標籤可以這樣定義

element=driver.find_element(By.ID,'loginForm')

4.2. 按名稱定位

當您知道元素的名稱屬性時使用它。使用此策略,將返回具有匹配名稱屬性的第一個元素。如果沒有元素具有匹配的nameNoSuchElementException屬性,將引發a 。

例如,考慮這個頁面源:

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
</body>
</html>
#定位其中的用戶名稱和密碼
username=driver.find_element(By.NAME,'username')
password=driver.find_element(By.NAME,'password')

這將給出“登錄”按鈕,因為它出現在“清除”按鈕之前:

continue = driver.find_element(By.NAME, 'continue')


4.3. 通過 XPath 定位

XPath 是用於在 XML 文檔中定位節點的語言。由於 HTML 可以是 XML (XHTML) 的實現,Selenium 用戶可以利用這種強大的語言來定位其 Web 應用程序中的元素。XPath 支持通過 id 或 name 屬性定位的簡單方法,並通過打開各種新的可能性(例如定位頁面上的第三個複選框)來擴展它們。

使用 XPath 的主要原因之一是當您沒有適合您希望定位的元素的 id 或 name 屬性時。您可以使用 XPath 以絕對方式(不建議)或相對於具有 id 或 name 屬性的元素來定位元素。XPath 定位符也可用於通過 id 和 name 以外的屬性指定元素。

絕對 XPath 包含從根 (html) 開始的所有元素的位置,因此很可能只對應用程序進行最輕微的調整就會失敗。通過查找具有 id 或 name 屬性的附近元素(最好是父元素),您可以根據關係定位目標元素。這不太可能改變,並且可以使您的測試更加健壯。

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
</body>
</html>

表單元素可以這樣定位:

login_form = driver.find_element(By.XPATH, "/html/body/form[1]")
login_form = driver.find_element(By.XPATH, "//form[1]")
login_form = driver.find_element(By.XPATH, "//form[@id='loginForm']")
  1. 絕對路徑(如果 HTML 只是稍微改變就會中斷)
  2. HTML 中的第一個表單元素
  3. 屬性id設置為loginForm 的表單元素

用戶名稱可以這樣定位

#定位其中的用戶名稱和密碼
username=driver.find_element(By.XPATH,'//form[input/@name="username"]')
username=driver.find_element(By.XPATH,'//form[@id="loginForm"]/input[1]')
username=driver.find_element(By.XPATH,'//input[@name="username"]')

  1. 具有名稱設置為用戶名的輸入子元素的第一個表單元素
  2. 屬性id設置為 loginForm的表單元素的第一個輸入子元素
  3. 屬性名稱設置為用戶名的第一個輸入元素
#清除按鈕元素
clear_button=driver.find_element(By.XPATH,'//input[@name="continue"][@type="button"]')
clear_button=driver.find_element(By.XPATH,'//form[@id="loginForm"]/input[4]')

  1. 輸入屬性名稱設置為繼續,屬性類型設置為 按鈕
  2. 屬性id設置為 loginForm 的表單元素的第四個輸入子元素


4.4. 通過鏈接文本定位超鏈接

當您知道錨標記中使用的鏈接文本時使用它。使用此策略,將返回鏈接文本與提供的值匹配的第一個元素。如果沒有元素具有匹配的鏈接文本屬性, NoSuchElementException將引發 a 。

例如,考慮這個頁面源:

<html>
 <body>
  <p>Are you sure you want to do this?</p>
  <a href="continue.html">Continue</a>
  <a href="cancel.html">Cancel</a>
</body>
</html>



#continue.html 鏈接可以這樣定位:
element=driver.find_element(By.LINK_TEXT,'Continue')
element=driver.find_element(By.PARTIAL_LINK_TEXT,'Conti')


4.6. 按類名定位元素

當你想通過類名定位元素時使用它。使用此策略,將返回具有匹配類名屬性的第一個元素。如果沒有元素具有匹配的類名屬性,NoSuchElementException 將引發 a 。

例如,考慮這個頁面源:

<html>
 <body>
  <p class="content">Site content goes here.</p>
</body>
</html>
#p元素可以這樣定位:
element=driver.find_element(By.TAG_NAME,'p')
#但通常網頁會有許多p元素所以選擇比較具有指標性的定位
element=driver.find_element(By.CLASS_NAME,'content')


4.7. 通過 CSS 選擇器定位元素

當您想使用CSS 選擇 器語法定位元素時使用此選項。使用此策略,將返回與給定 CSS 選擇器匹配的第一個元素。如果沒有元素與提供的 CSS 選擇器匹配, NoSuchElementException將引發 a 。

例如,考慮這個頁面源:

<html>
 <body>
  <p class="content">Site content goes here.</p>
</body>
</html>



#p元素可以這樣定位
element=driver.find_element(By.CSS_SELECTOR,'p.content')















 

標籤:

0 個意見:

張貼留言

訂閱 張貼留言 [Atom]

<< 首頁