使用 Selenium 处理拼图验证码,尝试次数限制为 5 次

问题描述 投票:0回答:1

我一直在抓取这个网站:https://www.immobilienscout24.de

当用selenium打开网站时,网站有时会在你点击“你不是机器人”验证码后给你解决一个谜题验证码。问题是该网站只允许你移动拼图 6 次。如果您在第六次之后未能将拼图放在正确的位置,将禁止您进入该网站。

代码移动了拼图,但是我如何安排 for 循环将屏幕分成 6 个确切的部分?或者如果有人有某种不同的方法?

拼图验证码的代码如下:

try:
    slider = driver.find_element(By.CLASS_NAME, 'geetest_slider_button')
    for x in range(0, 200, 10):
        actions.move_to_element(slider).click_and_hold().move_by_offset(x, 0).release().perform()
        time.sleep(0.1)
except:
    print('No slider found. Continuing with the code.')

谢谢你。

python selenium-webdriver recaptcha
1个回答
0
投票

根据我对您问题的理解,您的目标是在六次尝试内验证图片验证码。

这是一个非常复杂的问题,我认为最好的解决方案是直接将图像交给AI进行图像排序,这样会更容易。但我没有调用相关AI API的资格。也许您可以尝试激活它们。至于调用AI的代码,我觉得并不难。

排除使用AI的可能性,我相信仅仅通过模拟拖放来达到你的目标是不会成功的。

首先,您需要通过任何必要的手段捕获验证码区域,最终获得六张无序图像。例如,您可以捕获单个无序图像,然后在本地对其进行切片,或者直接从网页源代码中获取图像资源。

假设您已经完成这一步并获得了六张图像,您可以继续合并它们并进行图像采样。采样的方式有很多种,比如先将图像设置为灰度,然后进行轮廓提取。这样,您就得到了等高线图。一般来说,由于单幅图像存在亮度梯度,图像之间会有明显的分割线。当然,为了得到这些不同的特征线,你可能需要在轮廓提取过程中不断改变参数。不过由于图片已经下载到本地了,所以还是可以暴力破解这个问题。

大多数情况下,我们在边缘测试中无法达到100%的匹配,因此需要为每个边缘匹配结果建立特征值。完成序列的所有排列组合后,使用最高的特征值来移动图像。如果仍有剩余尝试次数,您可以继续使用排名较低的序列。

您可能会问,当您没有绝对正确的图像进行边缘匹配比较时,如何建立特征值。我的想法是你可以扭转你的做法。例如,手动创建空白图像,并在分割线的位置人为地绘制对比线。之后,提取该图像的轮廓作为你的特征值的参考。

另外,另一个想法是直接对这六张图像应用边缘匹配算法,将它们成对匹配,并计算最终的匹配值。

以上是我的思考过程,下面可能是该过程中涉及的潜在代码。

  1. 边缘匹配
def match_edges(image1, image2):
    # Convert images to grayscale
    gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

    # Detect edges in the images using the Canny algorithm
    edges1 = cv2.Canny(gray1, 50, 150)
    edges2 = cv2.Canny(gray2, 50, 150)

    # Initialize variables for matching edges
    # This example simplifies the matching process for demonstration purposes
    height, width = edges1.shape
    best_match_value = float('inf')
    best_match_position = None
    
    # Assuming edge matching is performed side by side (left/right edges comparison)
    for y in range(height):
        # Calculate the difference between edges of the two images
        match_value = np.sum(np.bitwise_xor(edges1[y,:], edges2[y,:]))
        # Update the best match if the current match is better
        if match_value < best_match_value:
            best_match_value = match_value
            best_match_position = y

    # Return the position and value of the best match
    return best_match_position, best_match_value
  1. 特征提取

# Restore picture 
f = merge(sum_rows,sum_cols,channels,part1,part2,part3,part4)
show_images([f],'Restore picture[1,2,3,4]')

# Gray
gray = cv2.cvtColor(f, cv2.COLOR_BGRA2GRAY)
show_images([gray],'Gray')

# Extract contour
edges = cv2.Canny(gray, 35, 80, apertureSize=3)
show_images([edges],'Extract contour')

  1. 绘制特征线
# f is current unsorted merge-image 
f = merge(sum_rows,sum_cols,channels,part1,part2,part3,part4)
lf = f.copy()
cv2.line(lf, (0, 75), (300, 75), (0, 0, 255), 2)
cv2.line(lf, (150, 0), (150, 150), (0, 0, 255), 2)
show_images([lf],'out of order,The gradient becomes the cross feature line.')
  1. 功能匹配
f = merge(sum_rows,sum_cols,channels,part1,part2,part3,part4)
gray = cv2.cvtColor(f, cv2.COLOR_BGRA2GRAY)
edges = cv2.Canny(gray, 35, 80, apertureSize=3)
show_images([edges],'Extract contour')
# find the split line.
lines = cv2.HoughLinesP(edges,0.01,np.pi/360,60,minLineLength=50,maxLineGap=10)
if lines is None:
    print('No cross feature line found')
else:
    lf = f.copy()
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv2.line(lf, (x1, y1), (x2, y2), (0, 0, 255), 2)
    show_images([lf])

Reference:

platform.openai.com/docs/guides/function-calling
zhihu.com/p/434851845    
geeksforgeeks.org/feature-detection-and-matching-with-opencv-python
© www.soinside.com 2019 - 2024. All rights reserved.