本文主要介紹了如何利用Selenium對網(wǎng)站進行登錄,Xpath元素定位,及窗口操作的一些常用方法,附上詳細代碼及解析,同時簡單總結(jié)元素定位不到的原因有哪些。雙擊下面圖片查看動圖
雙擊圖片,查看效果

一 圖片驗證碼登錄
這部分主要完成瀏覽器打開,通過元素定位在瀏覽器中輸入賬號、密碼信息,最后通過OCR識別技術(shù)完成驗證碼的輸入,保證登錄成功。
1.1啟用瀏覽器并打開測試網(wǎng)站
代碼:

From selenium import webdriver #將webdriver驅(qū)動導(dǎo)入selenium框架中
from pip._vendor.requests.cookies import get_cookie_header
#導(dǎo)入cookie(獲取cookie時使用)
import time#導(dǎo)入時間包(后續(xù)time函數(shù)使用)
#將chrome驅(qū)動地址賦值給chromdriver
browser=webdriver.Firefox()#打開Firefox瀏覽器
browser.get("https://login.xxxx.com/en?dest_url=https://xxxx.com/en/contact")
#打開測試網(wǎng)站(此網(wǎng)站地址需要填寫自己測試的網(wǎng)站地址)
1.2設(shè)置等待時間

在上面登錄過程中網(wǎng)頁加載慢,出現(xiàn)了還沒等圖片完全加載出來就進行圖片識別的現(xiàn)象,導(dǎo)致識別失敗,如下圖
那么我們應(yīng)該如何操作去避免提前加載的現(xiàn)象呢?
如果給它加一個條件滿足(圖片驗證碼顯示完全)時:再進行圖片識別操作是否可行呢,我們來看看
Selenium有3種等待時間:
名稱 方法 特點
強制等待 Thread.sleep() 執(zhí)行到此時不管什么就固定的等待三秒之后再接著執(zhí)行后面的操作
隱式等待方法 implicitlyWait() 隱式等待采用全部設(shè)置,此方法針對執(zhí)行腳本的所有對象,等待10秒
顯示等待方法 WebDriverWait() 明確的要等到某個元素的出現(xiàn)或者是某個元素的可點擊等條件,等不到,就一直等,除非在規(guī)定的時間之內(nèi)都沒找到,那么就跳出Exception
這里使用WebDriverWait()方法:
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
driver :瀏覽器驅(qū)動名稱
timeout :最長超時時間,默認以秒為單位。
poll_frequency :檢測的間隔(步長)時間,默認為0.5S。
ignored_exceptions :超時后的異常信息,默認情況下拋NoSuchElementException異常
WebDriverWait()一般由until()或until_not()方法配合使用
HTML結(jié)構(gòu):

代碼:
Element=WebDriverWait(browser,100).until(
? ? EC.presence_of_element_located((By.ID,"captcha_img_id"))
)
代碼意思是:ID名稱為"captcha_img_id"的元素顯示等待100s,如果沒有出現(xiàn),拋出異常,通過上面方法就可以處理等待頁面元素加載完全后進行相關(guān)功能操作。
1.3賬號、密碼元素定位并輸入內(nèi)容

首先通過F12打開代碼界面,點擊元素定位圖標,選中要定位的“賬號”文本框內(nèi)容,在代碼區(qū)域找到定位的元素代碼信息,如下圖中的name名稱“l(fā)ogin”,密碼元素同理
代碼:
browser.find_element_by_name("Login").send_keys("xxxx")
#通過name定位登錄文本框,通過send_keys輸入賬戶信息
browser.find_element_by_name("Password").send_keys("xxxx")
#通過name定位密碼文本框,通過send_keys輸入密碼信息
1.4驗證碼處理-使用OCR自動識別
看網(wǎng)上介紹驗證碼處理大致有4種方法,1.讓開發(fā)把驗證碼代碼注釋掉 2.讓開發(fā)設(shè)置萬能驗證碼 3.通過添加cookie方式繞過圖片驗證碼 4.OCR自動識別,其中1-2因為這個網(wǎng)站與開發(fā)接觸不到,不予考慮方法3一般適用于記住登錄狀態(tài)的網(wǎng)站才適合,這里我使用第4種方法,這種方法適合于處理比較簡單的驗證碼
OCR自動識別的原理是什么呢?
在這里我們需要使用pytesseract,它是一款用于光學(xué)字符識別(OCR)的python工具,即從圖片中識別出其中嵌入的文字。整個過程分為截取登錄頁面->獲取驗證碼的位置坐標->打開截圖->從截圖中截取驗證碼的區(qū)域->使用pytesseract工具識別驗證碼
代碼:
browser.save_screenshot('f://a.png')#截取當(dāng)前網(wǎng)頁,該網(wǎng)頁有我們需要的驗證碼
yzm=browser.find_element_by_id("captcha_img_id") #定位驗證碼
location=yzm.location#獲取驗證碼x,y軸坐標
size=yzm.size#獲取驗證碼的長寬
rangle=(int(location['x']),int(location['y']),int(location['x']+size['width']),int(location['y']+size['height']))#截取的位置坐標
i=Image.open("f://a.png") #打開截圖
frame4=i.crop(rangle) #使用Image的crop函數(shù),從截圖中再次截取我們需要的區(qū)域
frame4.save('f://frame4.jpg')#將截取到的驗證碼保存為jpg圖片
qq=Image.open('f://frame4.jpg')#打開jpg驗證碼圖片
text=pytesseract.image_to_string(qq).strip() #使用image_to_string識別驗證碼
browser.find_element_by_name("turing").send_keys(text)#將識別的圖片驗證碼信息輸入到驗證碼輸入文本框中
browser.find_element_by_class_name("btn").click()#點擊登錄按鈕
運行代碼后可能會遇到提示“系統(tǒng)找不到指定文件”

這個問題困擾了我好久,最后處理方案如下:
首先保證pytesseract環(huán)境安裝正確-參見pytesseract環(huán)境安裝文章:
https://www.cnblogs.com/hupeng1234/p/7136442.html
其次,打開文件 pytesseract.py,找到如下代碼,將tesseract_cmd的值修改為全路徑如:
tesseract_cmd = 'C:\\Program Files\\Tesseract-OCR\\tesseract'#這里一定要用\\不能用\,在程序里\\表示轉(zhuǎn)譯,如果只使用\是沒用的。
運行代碼,圖1中的整個自動登錄功能就實現(xiàn)了,怎么樣有沒有一種要飛的感覺…
二Firepath工具方法定位元素
2.1 實現(xiàn)的主要功能
點擊用戶名稱,選擇選中下拉菜單選項進入詳細頁面
借助Firebug和Firepath工具,方便我們使用Xpath對元素進行定位,這里我們使用Xpath定位,一般都通過Xpath結(jié)合屬性值進行定位元素,95%以上的定位都能通過此方法解決
2.2具體操作
1. 首先下載Firebug和Firepath工具,下載步驟:工具-web開發(fā)者-獲取更多工具-搜索框搜索Firebug-添加到Firefox即可【Firepath同理】

2. 工具使用,firefox中按[F12]
(1) 在Firebug 選項左鍵單擊
(2) 右鍵選中要定位的元素選擇【使用Firebug查找元素】
(3) 右鍵選中高亮代碼,右鍵選擇在FirePath面板中查看
(4) FirePath下文本框內(nèi)容就是Xpath定位命令,拷貝命定到代碼編輯器中(elipse)
HTML代碼:


3. 定位Xpath元素,實現(xiàn)點擊按鈕
browser.find_element_by_xpath("http://*[@id='navbar']/ul[2]/li[1]/a").click()
其中“//*[@id='navbar']/ul[2]/li[1]/a”這句話表示什么意思呢,跟著我一步一步看,(1)//表示在文檔的全部層級進行查找
(2)[@id='navbar']表示定位id='navbar'元素下
(3)ul[2]表示定位到第二個無序列表的樣式ul下
(4)li[1]表示定位到第一個列表內(nèi)行的樣式li下
(5)a表示定位到超鏈接下
從(1)到(5)是逐級展開的
4. 通過link text定位元素實現(xiàn)跳轉(zhuǎn)

實現(xiàn)代碼:browser.find_element_by_link_text("Discover").click()
(1) by_link_text:文本鏈接方式
(2) click():鼠標點擊功能
Firepath工具可以幫助我們輕松定位元素,對于初學(xué)者是一個非常不錯的工具,熟練之后再慢慢練習(xí)自己寫。
三.元素定位不到原因分析--窗口句柄

在程序運行過程中,一直提示元素定位不到“unable to locate element”,這個問題我解決了大概有一個星期,下面是我的解決思路。
頁面元素結(jié)構(gòu):
定位代碼:
browser.find_element_by_xpath("http://form/div/div/descendant::a[@href='/adview']").click()
1. 無論怎么定位都提示“unable to locate element”,如下圖

于是就開啟了找問題出在哪里
3.1.網(wǎng)上查定位元素不到的原因有哪些
首先,我在網(wǎng)上查元素定位不到的原因,因為根據(jù)提示,我們知道是元素沒有定位成功
網(wǎng)上的思路大概都是:
1. 定位的ID是動態(tài),這里不涉及ID,所以排除
2. iframe原因定位不到元素
3. 不在同一個frame里邊查找元素,這里不涉及iframe元素,所以2/3排除
4. Xpath描述錯誤
剛開始我以為是我元素定位的錯誤,所以花了很多時間在換各種方式進行定位:包括使用Selenium IDE 工具、使用Link()方法、利用Firepath 中的Xpath Css定位,仍提示定位不成功
5. 點擊速度過快 頁面沒有加載出來就需要點擊頁面上的元素
我在語句前面加上加載時間time.sleep(5)等待,還是不行
6. firefox安全性強,不允許跨域調(diào)用出現(xiàn)報錯
錯誤描述:uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIDOMNSHTMLDocument.execCommand]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location:
根據(jù)錯誤描述,這點也不符合,排除
3.2. 如何排除不是語句錯誤
根據(jù)之前操作,感覺不應(yīng)該定位語句錯誤的原因,所以如何排除判斷是不是語句錯誤呢
1. 因為這個頁面屬于登錄成功后調(diào)用的第二個頁面,所以我從上一頁面開始,把之前的代碼前加上注釋#后運行
2.結(jié)果調(diào)用成功了,直接跳轉(zhuǎn)到第三個頁面了,可以說明語句沒有編寫錯誤
3.這里還有一個方法,就是你換其他瀏覽器試一試,但是我覺得還得重新配置太麻煩了
3.3 罪魁禍首-窗口句柄
既然語句編寫的沒有問題,那么我又開始懷疑人生了,到低哪里出錯了
1. 繼續(xù)網(wǎng)上找資料,發(fā)現(xiàn)是從a頁面到b頁面,窗口句柄還停留在上一個頁面,所以無法定位元素
窗口句柄是什么
想要在某個窗口做一些事情,你就得讓操作系統(tǒng)知道你是在哪一個窗口做這些事情,而窗口的句柄就能起到識別哪一個窗口的作用
所以剛剛進入到一個頁面后,將窗口進行重新定位應(yīng)該就可以了
time.sleep(5
browser.switch_to_window(browser.window_handles[1])
browser.find_element_by_xpath("http://form/div/div/descendant::a[@href='/adview']").click()
總結(jié):以后再遇到跳轉(zhuǎn)新頁面的時候不要忘記加窗口句柄?。?!
本篇文章就到這里,附上所有運行代碼:
# coding=gbk
'''
Created on 2018年3月8日
@author: Administrator
'''
#!/usr/bin/python
# -*-encoding:utf-8 -*-
#1.啟用瀏覽器并打開測試網(wǎng)站
from PIL import Image
import pytesseract
from selenium import webdriver #將webdriver驅(qū)動導(dǎo)入selenium框架中
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pip._vendor.requests.cookies import get_cookie_header#導(dǎo)入cookie
import time#導(dǎo)入時間包
from pydoc import browse
from pip import locations
from test.test_largefile import size
from _elementtree import Element
from select import select
from cgitb import text
from test.test_os import LoginTests
#chromedriver="C:\Program Files\Internet Explorer\IEDriverServer.exe"#將chrome驅(qū)動地址賦值給chromdriver
#browser=webdriver.Chrome()
browser=webdriver.Firefox()
browser.get("https://login.acesse.com/en?dest_url=https://acesse.com/en/contact")#打開測試網(wǎng)站?
Element=WebDriverWait(browser,100).until(
? ? EC.presence_of_element_located((By.ID,"captcha_img_id"))
? ? )
#2.對賬號、密碼元素進行定位
browser.find_element_by_name("Login").send_keys("xxxxx")
browser.find_element_by_name("Password").send_keys("xxxxxxx")
#3.驗證碼處理-使用OCR自動識別
#browser.maximize_window()
def login():
? ? browser.save_screenshot('f://a.png')#截取當(dāng)前網(wǎng)頁,該網(wǎng)頁有我們需要的驗證碼
? ? yzm=browser.find_element_by_id("captcha_img_id") #定位驗證碼
? ? location=yzm.location#獲取驗證碼x,y軸坐標
? ? size=yzm.size#獲取驗證碼的長寬
rangle=(int(location['x']),int(location['y']),int(location['x']+size['width']),int(location['y']+size['height']))#截取的位置坐標
? ? i=Image.open("f://a.png") #打開截圖
? ? frame4=i.crop(rangle) #使用Image的crop函數(shù),從截圖中再次截取我們需要的區(qū)域
? ? frame4= frame4.convert('RGB')
? ? frame4.save('f://frame4.jpeg')#講截取到的驗證碼保存為jpg圖片
? ? qq=Image.open('f://frame4.jpeg')#打開jpg驗證碼圖片
? ? text=pytesseract.image_to_string(qq).strip() #使用image_to_string識別驗證碼
? ? browser.find_element_by_name('turing').send_keys(text)#將識別的圖片驗證碼信息輸入到驗證碼輸入文本框中
? ? browser.find_element_by_class_name("btn").click()#點擊登錄按鈕
login()
browser.find_element_by_xpath("/html/body/div[1]/nav/div/div[3]/ul[2]/li[2]/a").click()
browser.find_element_by_xpath('/html/body/div[1]/nav/div/div[3]/ul[2]/li[2]/ul/li[6]/a/span').click()
#browser.implicitly_wait(30)
time.sleep(5)
browser.switch_to_window(browser.window_handles[1])
browser.find_element_by_xpath("http://form/div/div/descendant::a[@href='/adview']").click()