為什麼Selenium點不到元素
來自專欄萌新的學習日記18 人贊了文章
為什麼Selenium點不到元素
最近做了許多登陸項目,我會優先選擇使用requests來模擬請求,但是有些參數實在是很難獲取,這個時候我會使用Selenium,也還是遇到了各種坑,也算是見識到了很多的驗證措施。
今天說說如何解決selenium點選不到數據的問題。
等待
這還是最常見的一種情況,推薦最多的是使用顯示等待:
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECdriver = webdriver.Firefox()driver.get("http://somedomain/url_that_delay_loading")try: element = WebDriverWait(driver,10).until( EC.presence_of_element_located((By.ID,"myDynamicElement")) )finally: driver.quit()
這段代碼會等待10秒,如果10秒內找到元素則立即返回,否則會拋出TimeoutException異常。
但是我比較懶,因為time.sleep()
可以達到同樣效果。
滑鼠事件
官方把它叫做「行為鏈」。ActionChains可以完成簡單的交互行為,例如滑鼠移動,滑鼠點擊事件,鍵盤輸入,以及內容菜單交互。
click(on_element=None) ——單擊滑鼠左鍵click_and_hold(on_element=None) ——點擊滑鼠左鍵,不鬆開context_click(on_element=None) ——點擊滑鼠右鍵double_click(on_element=None) ——雙擊滑鼠左鍵drag_and_drop(source, target) ——拖拽到某個元素然後鬆開drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某個坐標然後鬆開key_down(value, element=None) ——按下某個鍵盤上的鍵key_up(value, element=None) ——鬆開某個鍵move_by_offset(xoffset, yoffset) ——滑鼠從當前位置移動到某個坐標move_to_element(to_element) ——滑鼠移動到某個元素move_to_element_with_offset(to_element, xoffset, yoffset) ——移動到距某個元素(左上角坐標)多少距離的位置perform() ——執行鏈中的所有動作release(on_element=None) ——在某個元素位置鬆開滑鼠左鍵send_keys(*keys_to_send) ——發送某個鍵到當前焦點的元素send_keys_to_element(element, *keys_to_send) ——發送某個鍵到指定元素
深入了解可以參考 https://blog.csdn.net/huilan_same/article/details/52305176
move_to_element_with_offset
和click_and_hold
會經常用到破解驗證碼中。
觸摸操作 (TouchAction)
該事件僅僅針對移動端、觸屏版
flick_element(on_element, xoffset, yoffset, speed) # 以元素為起點以一定速度向下滑動scroll_from_element(on_element xoffset yoffset) #以元素為起點向下滑動double_tap(on_element) #雙擊 flick_element(on_element, xoffset, yoffset, speed) #從元素開始以指定的速度移動long_press(on_element) #長按不釋放move(xcoord, ycoord) #移動到指定的位置perform() #執行鏈中的所有動作release(xcoord, ycoord) #在某個位置鬆開操作scroll(xoffset, yoffset) #滾動到某個位置scroll_from_element(on_element, xoffset, yoffset) #從某元素開始滾動到某個位置tap(on_element) #單擊tap_and_hold(xcoord, ycoord) #某點按住
為什麼要說到移動端,在做登陸時,移動端往往會更加簡單,但是觸屏版的點擊和PC端時完全不同的,點擊與按住時不同的。
在某個項目我換成TouchAction
後,神奇的發現,註冊不再需要處理驗證碼了,真是太棒了。
使用js
當你使用瀏覽器已經找到該元素,使用click()
方法但是不起作用時,這個時候建議嘗試js,例如在我的主頁 https://www.zhihu.com/people/cuishite/activities,點擊 「查看詳細資料」
js = document.getElementsByClassName("Button ProfileHeader-expandButton Button--plain")[0].click();driver.execute_script(js)
你可以先在控制台調試
js通常可以解決絕大多是問題,如果還是解決不了,那你可能和我遇到了同樣的問題,比如說,我在處理某移動端網站登陸,處理如下驗證碼時,我會使用到move_to_element_with_offset
,該方法是「移動到距某個元素(左上角坐標)多少距離的位置」。
計算出坐標後,會調用該方法,如action.move_to_element_with_offset(element, width, height).click().perform()
,然而實際上問題並沒有這麼簡單,多次點擊失效。具體的有時間再說。
實用方法
提取selenium的cookies
介紹把selenium的cookies船體給requests使用的方法:
cookies = driver.get_cookies()s = requests.Session()for cookie in cookies: s.cookies.set(cookie[name], cookie[value])
How do I load session and cookies from Selenium browser to requests library in Python?
元素截圖方法
from selenium import webdriverfrom PIL import Imagefox = webdriver.Firefox()fox.get(https://stackoverflow.com/)# now that we have the preliminary stuff out of the way time to get that image element = fox.find_element_by_id(hlogo) # find part of the page you want image oflocation = element.locationsize = element.sizefox.save_screenshot(screenshot.png) # saves screenshot of entire pagefox.quit()im = Image.open(screenshot.png) # uses PIL library to open image in memoryleft = location[x]top = location[y]right = location[x] + size[width]bottom = location[y] + size[height]im = im.crop((left, top, right, bottom)) # defines crop pointsim.save(screenshot.png) # saves new cropped image
selenium cannot screenshot a web element
最後推薦一個神器 appium/python-client
至於驗證碼部分,現在主要還是靠第三方工具,並沒有自己嘗試機器學習等方法處理。
推薦閱讀:
※PyStarTrek
※Numpy之Meshgrid函數介紹
※一個完整的機器學習項目在Python中的演練(一)
※《Python之禪》事件之你們想要的實錘
※Python(4)-24點小遊戲計算