使用Selenium处理最多尝试5次的拼图验证码
我一直在抓取这个网站:https://www.immobilienscout24.de
当我用selenium打开这个网站时,有时候在点击“我不是机器人”的验证码后,网站会让你解一个拼图验证码。问题是,这个网站只允许你移动拼图6次。如果你在第六次之后还是没能把拼图放对位置,就会被禁止进入这个网站。
我的代码可以移动拼图,但我该如何安排循环,让屏幕分成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.')
谢谢。
1 个回答
根据我对你问题的理解,你的目标是在六次尝试内验证一个图片验证码。
这个问题非常复杂,我认为最好的解决办法是直接把图片交给人工智能来处理,这样会简单一些。不过,我没有资格去调用相关的人工智能接口。也许你可以试着去激活它们。至于调用人工智能的代码,我觉得这应该不难。
如果不考虑使用人工智能,我认为仅仅通过模拟拖放是无法实现你的目标的。
首先,你需要以任何可能的方式捕捉到验证码区域,最终得到六张乱序的图片。比如,你可以先捕捉一张乱序的图片,然后在本地对其进行切割,或者直接从网页的源代码中获取图片资源。
假设你已经完成了这一步,得到了六张图片,那么你可以继续合并它们并进行图像采样。有很多种采样的方法,比如先把图片转换为灰度图,然后提取轮廓。这样,你就能得到一张轮廓图。通常来说,单张图片的亮度会有渐变,因此不同图片之间会有明显的分界线。当然,为了得到这些清晰的特征线,你可能需要在提取轮廓的过程中不断调整参数。不过,由于这些图片已经下载到本地,你仍然可以通过暴力破解来解决这个问题。
大多数情况下,我们无法在边缘测试中达到100%的匹配,因此你需要为每个边缘匹配结果建立特征值。在完成所有的排列组合后,使用最高的特征值来移动图片。如果还有剩余的尝试次数,你可以继续使用排名较低的序列。
你可能会问,当没有绝对正确的图片用于边缘匹配比较时,如何建立特征值。我认为你可以反向思考这个问题。例如,手动创建一张空白图片,并在分界线的位置人工绘制对比线。之后,提取这张图片的轮廓,作为特征值的参考。
另外,还有一个想法是直接对这六张图片应用边缘匹配算法,成对匹配它们,并计算最终的匹配值。
以上是我的思考过程,下面是可能涉及到的代码。
- 边缘匹配
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
- 特征提取
# 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')
- 绘制特征线
# 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.')
- 特征匹配
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