如何在 Python 中仅使用 Selenium 长按(按住)鼠标左键
How to long press (Press and Hold) mouse left key using only Selenium in Python
我正在尝试使用 Python 中的 Selenium 从沃尔玛网站上抓取一些评论数据,但它连接此 site 以供人工验证。检查此“按住”按钮后,不知何故,当我找到该元素时,它以 [object HTMLIFrameElement] 的形式出现,而不是网络元素。并且该元素随机出现在任何 iframe 中,在 10 个 iframe 中。它可以使用循环来检查,但是,最终我们不能在没有 web 元素的情况下在 selenium 中采取任何行动。
虽然此验证也作为弹出窗口出现,但我试图先针对此页面解决它。我以某种方式使用 div
作为网络元素找到了此按钮的位置。
actions = ActionChains(driver)
iframe = driver.find_element_by_xpath("//div[@id='px-captcha']")
frame_x = iframe.location['x']
frame_y = iframe.location['y']
actions.move_to_element(iframe).move_by_offset(frame_x-550, frame_y+70).build().perform()
如果我执行 context.click()
或右键单击,可以看到鼠标位置在按钮的中间。
现在,如果我可以执行长按或按住鼠标左键一会儿,我想这个验证可以被清除。为此,我尝试在 action
中使用 click()
和 click_and_hold
以及 key_down
方法(按 ctrl 和 enter 与长按相同)进行操作,但是没有响应,因为这些方法释放按钮,不能长按。我试过了
actions.move_to_element(iframe).move_by_offset(frame_x-550,frame_y+70).click_and_hold().pause(20).perform()
actions.move_to_element(iframe).move_by_offset(frame_x-550, frame_y+70).actions.key_down(Keys.CONTROL).actions.key_down(Keys.ENTER).pause(20).perform()
.....还有很多方法! 我如何使用 Selenium 解决它?
这是我的临时解决方案。关键是10秒后松开再点击。这就是我如何能够欺骗验证码,让它认为我将其保持 只是 正确的时间(在我的实验中,验证码保持时间是随机的,10 秒确保足够是时候完全完成验证码了)。
element = driver.find_element_by_css_selector('#px-captcha')
action = ActionChains(driver)
click = ActionChains(driver)
action.click_and_hold(element)
action.perform()
time.sleep(10)
action.release(element)
action.perform()
time.sleep(0.2)
action.release(element)
这是处理长按验证码案例的完整代码。我已经添加了代码来自动调整验证码框的大小,以便在需要验证的验证码中间单击并按住。
import os
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.action_chains import ActionChains
import time
from time import sleep
from random import randint
chromedriver = "C:\Program Files\Python39\Scripts\chromedriver"
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
chromedriver = "C:\Program Files\Python39\Scripts\chromedriver"
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
url = "{Your URL}"
driver.get(url)
sleep(randint(2,3))
element = driver.find_element_by_xpath("//div[@id='px-captcha']")
# print(len(element.text), '- Value found by method text')
action = ActionChains(driver)
click = ActionChains(driver)
frame_x = element.location['x']
frame_y = element.location['y']
# print('x: ', frame_x)
# print('y: ', frame_y)
# print('size box: ', element.size)
# print('x max click: ', frame_x + element.size['width'])
# print('y max click: ', frame_y + element.size['height'])
x_move = frame_x + element.size['width']*0.5
y_move = frame_y + element.size['height']*0.5
action.move_to_element_with_offset(element, x_move, y_move).click_and_hold().perform()
time.sleep(10)
action.release(element)
action.perform()
time.sleep(0.2)
action.release(element)
@Prata Palit
'Press & Hold' 按钮使用 10 个 iframe,
随机一个 iframe 可见,其他 9 个 ifame 隐藏,
iframe 具有 cross-domain,无法获取具有 javascript 的元素。
'Press and hold' 按钮完成验证速度也是随机的。
我使用了 FLANN 的特征匹配。
- 获取经过验证的验证码图片https://i.stack.imgur.com/ADzMT.png
使用 selenium 屏幕截图获取验证码元素图像。
不要使用 OS 屏幕截图。
因为你需要比较相同的截图。
- 检查页面是否包含验证码
按住
每隔0.5秒循环执行以下操作
使用pre-prepared验证码与页面上的验证码进行比较
直到匹配或超时
匹配验证码https://i.stack.imgur.com/xCqhy.jpg
def solve_blocked(self, retry=3):
'''
Solve blocked
(Cross-domain iframe cannot get elements temporarily)
Simulate the mouse press and hold to complete the verification
'''
if not retry:
return False
element = None
try:
element = WebDriverWait(self.browser,15).until(EC.presence_of_element_located((By.ID,'px-captcha')))
# Wait for the px-captcha element styles to fully load
time.sleep(0.5)
except BaseException as e:
self.logger.info(f'px-captcha element not found')
return
self.logger.info(f'solve blocked:{self.browser.current_url}, Retry {retry} remaining times')
template = cv2.imread(os.path.join(settings.TPL_DIR, 'captcha.png'), 0)
# Set the minimum number of feature points to match value 10
MIN_MATCH_COUNT = 8
if element:
self.logger.info(f'start press and hold')
ActionChains(self.browser).click_and_hold(element).perform()
start_time = time.time()
while 1:
# timeout
if time.time() - start_time > 20:
break
x, y = element.location['x'], element.location['y']
width, height = element.size.get('width'), element.size.get('height')
left = x*self.pixelRatio
top = y*self.pixelRatio
right = (x+width)*self.pixelRatio
bottom = (y+height)*self.pixelRatio
# full screenshot
png = self.browser.get_screenshot_as_png()
im = Image.open(BytesIO(png))
# px-captcha screenshot
im = im.crop((left, top, right, bottom))
target = cv2.cvtColor(np.asarray(im),cv2.COLOR_RGB2BGR)
# Initiate SIFT detector
sift = cv2.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(template,None)
kp2, des2 = sift.detectAndCompute(target,None)
# create set FLANN match
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)
# store all the good matches as per Lowe's ratio test.
good = []
# Discard matches greater than 0.7
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
self.logger.info( "matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT))
if len(good)>=MIN_MATCH_COUNT:
self.logger.info(f'release button')
ActionChains(self.browser).release(element).perform()
return
time.sleep(0.5)
time.sleep(1)
retry -= 1
self.solve_blocked(retry)
我正在尝试使用 Python 中的 Selenium 从沃尔玛网站上抓取一些评论数据,但它连接此 site 以供人工验证。检查此“按住”按钮后,不知何故,当我找到该元素时,它以 [object HTMLIFrameElement] 的形式出现,而不是网络元素。并且该元素随机出现在任何 iframe 中,在 10 个 iframe 中。它可以使用循环来检查,但是,最终我们不能在没有 web 元素的情况下在 selenium 中采取任何行动。
虽然此验证也作为弹出窗口出现,但我试图先针对此页面解决它。我以某种方式使用 div
作为网络元素找到了此按钮的位置。
actions = ActionChains(driver)
iframe = driver.find_element_by_xpath("//div[@id='px-captcha']")
frame_x = iframe.location['x']
frame_y = iframe.location['y']
actions.move_to_element(iframe).move_by_offset(frame_x-550, frame_y+70).build().perform()
如果我执行 context.click()
或右键单击,可以看到鼠标位置在按钮的中间。
现在,如果我可以执行长按或按住鼠标左键一会儿,我想这个验证可以被清除。为此,我尝试在 action
中使用 click()
和 click_and_hold
以及 key_down
方法(按 ctrl 和 enter 与长按相同)进行操作,但是没有响应,因为这些方法释放按钮,不能长按。我试过了
actions.move_to_element(iframe).move_by_offset(frame_x-550,frame_y+70).click_and_hold().pause(20).perform()
actions.move_to_element(iframe).move_by_offset(frame_x-550, frame_y+70).actions.key_down(Keys.CONTROL).actions.key_down(Keys.ENTER).pause(20).perform()
.....还有很多方法! 我如何使用 Selenium 解决它?
这是我的临时解决方案。关键是10秒后松开再点击。这就是我如何能够欺骗验证码,让它认为我将其保持 只是 正确的时间(在我的实验中,验证码保持时间是随机的,10 秒确保足够是时候完全完成验证码了)。
element = driver.find_element_by_css_selector('#px-captcha')
action = ActionChains(driver)
click = ActionChains(driver)
action.click_and_hold(element)
action.perform()
time.sleep(10)
action.release(element)
action.perform()
time.sleep(0.2)
action.release(element)
这是处理长按验证码案例的完整代码。我已经添加了代码来自动调整验证码框的大小,以便在需要验证的验证码中间单击并按住。
import os
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.action_chains import ActionChains
import time
from time import sleep
from random import randint
chromedriver = "C:\Program Files\Python39\Scripts\chromedriver"
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
chromedriver = "C:\Program Files\Python39\Scripts\chromedriver"
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
url = "{Your URL}"
driver.get(url)
sleep(randint(2,3))
element = driver.find_element_by_xpath("//div[@id='px-captcha']")
# print(len(element.text), '- Value found by method text')
action = ActionChains(driver)
click = ActionChains(driver)
frame_x = element.location['x']
frame_y = element.location['y']
# print('x: ', frame_x)
# print('y: ', frame_y)
# print('size box: ', element.size)
# print('x max click: ', frame_x + element.size['width'])
# print('y max click: ', frame_y + element.size['height'])
x_move = frame_x + element.size['width']*0.5
y_move = frame_y + element.size['height']*0.5
action.move_to_element_with_offset(element, x_move, y_move).click_and_hold().perform()
time.sleep(10)
action.release(element)
action.perform()
time.sleep(0.2)
action.release(element)
@Prata Palit
'Press & Hold' 按钮使用 10 个 iframe,
随机一个 iframe 可见,其他 9 个 ifame 隐藏,
iframe 具有 cross-domain,无法获取具有 javascript 的元素。
'Press and hold' 按钮完成验证速度也是随机的。
我使用了 FLANN 的特征匹配。
- 获取经过验证的验证码图片https://i.stack.imgur.com/ADzMT.png
使用 selenium 屏幕截图获取验证码元素图像。
不要使用 OS 屏幕截图。 因为你需要比较相同的截图。 - 检查页面是否包含验证码
按住
每隔0.5秒循环执行以下操作
使用pre-prepared验证码与页面上的验证码进行比较
直到匹配或超时
匹配验证码https://i.stack.imgur.com/xCqhy.jpg
def solve_blocked(self, retry=3):
'''
Solve blocked
(Cross-domain iframe cannot get elements temporarily)
Simulate the mouse press and hold to complete the verification
'''
if not retry:
return False
element = None
try:
element = WebDriverWait(self.browser,15).until(EC.presence_of_element_located((By.ID,'px-captcha')))
# Wait for the px-captcha element styles to fully load
time.sleep(0.5)
except BaseException as e:
self.logger.info(f'px-captcha element not found')
return
self.logger.info(f'solve blocked:{self.browser.current_url}, Retry {retry} remaining times')
template = cv2.imread(os.path.join(settings.TPL_DIR, 'captcha.png'), 0)
# Set the minimum number of feature points to match value 10
MIN_MATCH_COUNT = 8
if element:
self.logger.info(f'start press and hold')
ActionChains(self.browser).click_and_hold(element).perform()
start_time = time.time()
while 1:
# timeout
if time.time() - start_time > 20:
break
x, y = element.location['x'], element.location['y']
width, height = element.size.get('width'), element.size.get('height')
left = x*self.pixelRatio
top = y*self.pixelRatio
right = (x+width)*self.pixelRatio
bottom = (y+height)*self.pixelRatio
# full screenshot
png = self.browser.get_screenshot_as_png()
im = Image.open(BytesIO(png))
# px-captcha screenshot
im = im.crop((left, top, right, bottom))
target = cv2.cvtColor(np.asarray(im),cv2.COLOR_RGB2BGR)
# Initiate SIFT detector
sift = cv2.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(template,None)
kp2, des2 = sift.detectAndCompute(target,None)
# create set FLANN match
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)
# store all the good matches as per Lowe's ratio test.
good = []
# Discard matches greater than 0.7
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
self.logger.info( "matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT))
if len(good)>=MIN_MATCH_COUNT:
self.logger.info(f'release button')
ActionChains(self.browser).release(element).perform()
return
time.sleep(0.5)
time.sleep(1)
retry -= 1
self.solve_blocked(retry)