为什么Selenium点不到元素

2018-08-08 17:13:52 浏览数 (1)

最近做了许多登陆项目,我会优先选择使用requests来模拟请求,但是有些参数实在是很难获取,这个时候我会使用Selenium,也还是遇到了各种坑,也算是见识到了很多的验证措施。

今天说说如何解决selenium点选不到数据的问题。

等待

这还是最常见的一种情况,推荐最多的是使用显示等待:

代码语言:javascript复制
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = 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可以完成简单的交互行为,例如鼠标移动,鼠标点击事件,键盘输入,以及内容菜单交互。

代码语言:javascript复制
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_offsetclick_and_hold会经常用到破解验证码中。

触摸操作 (TouchAction)

该事件仅仅针对移动端、触屏版

代码语言:javascript复制
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,点击 “查看详细资料”

python 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使用的方法:

代码语言:javascript复制
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?

元素截图方法

代码语言:javascript复制
from selenium import webdriver
from PIL import Image

fox = webdriver.Firefox()
fox.get('https://stackoverflow.com/')

# now that we have the preliminary stuff out of the way time to get that image :D
element = fox.find_element_by_id('hlogo') # find part of the page you want image of
location = element.location
size = element.size
fox.save_screenshot('screenshot.png') # saves screenshot of entire page
fox.quit()

im = Image.open('screenshot.png') # uses PIL library to open image in memory

left = location['x']
top = location['y']
right = location['x']   size['width']
bottom = location['y']   size['height']


im = im.crop((left, top, right, bottom)) # defines crop points
im.save('screenshot.png') # saves new cropped image

selenium cannot screenshot a web element

最后推荐一个神器 appium/python-client

至于验证码部分,现在主要还是靠第三方工具,并没有自己尝试机器学习等方法处理。

0 人点赞