由于本人近期参加一个游戏比赛,然后有个拉票的环节,票高者得人气奖。又比较懒不想到处拉票麻烦别人。就想自己尝试着破解验证码然后来达到刷票的目的。
这个也纯属娱乐,最后发现是不可行的。
最终目标:实现自动点击红星,并且拖动完成验证
自动模拟的过程通过 selenium
实现。
selenium安装过程自己上网找,很简单,还需要安装一个webdriver
class WangYi(object):
def __init__(self):
self.browser = webdriver.Edge()
self.back_img = None
self.cut_img = None
self.scaling_ratio = 1.0
def visit(self, url):
self.browser.get(url)
WebDriverWait(self.browser, 10, 0.5).until(EC.element_to_be_clickable((By.CLASS_NAME, 'big-heart')))
time.sleep(2)
self.browser.find_element_by_class_name("big-heart").click()
def get_image(self):
# 等待加载
WebDriverWait(self.browser, 10, 0.5).until(EC.visibility_of_element_located((By.CLASS_NAME, 'yidun_bgimg')))
back_url= self.browser.find_element_by_class_name("yidun_bg-img").get_attribute('src')
cut_url = self.browser.find_element_by_class_name("yidun_jigsaw").get_attribute('src')
# 从url获取图片并保存到本地
resq = requests.get(back_url)
file = BytesIO(resq.content)
back_img = Image.open(file)
back_img.save("back_img.jpg")
resq = requests.get(cut_url)
file = BytesIO(resq.content)
cut_img = Image.open(file)
cut_img.save("cut_img.png")
# opencv读取图片
self.back_img = cv2.imread("back_img.jpg")
self.cut_img = cv2.imread("cut_img.png")
self.scaling_ratio = self.browser.find_element_by_class_name("yidun_bg-img").size['width'] / back_width
return self.cut_img, self.back_img
计算滑动距离分为以下几步:
cv2.findContours
)提取单片拼图边缘轨迹并构造成一个二维矩阵(算子)cv2.GaussianBlur
)和 Canny 边缘检测算子( cv2.Canny
)对背景图进行处理,凸显出拼图在图片中的边缘还需要注意的就是,在图像中计算出来的距离还需要根据图片与实际web中的比例进行scaling
def get_distance(self):
back_canny = get_back_canny(self.back_img)
operator = get_operator(self.cut_img)
pos_x, max_value = best_match(back_canny, operator)
distance = pos_x * self.scaling_ratio
return distance
def read_img_file(cut_dir, back_dir):
cut_image = cv2.imread(cut_dir)
back_image = cv2.imread(back_dir)
return cut_image, back_image
def best_match(back_canny, operator):
max_value, pos_x = 0, 0
for x in range(cut_width, back_width - cut_width):
block = back_canny[:, x:x + cut_width]
value = (block * operator).sum()
if value > max_value:
max_value = value
pos_x = x
return pos_x, max_value
def get_back_canny(back_img):
img_blur = cv2.GaussianBlur(back_img, (3, 3), 0)
img_gray = cv2.cvtColor(img_blur, cv2.COLOR_BGR2GRAY)
img_canny = cv2.Canny(img_gray, 100, 200)
return img_canny
def get_operator(cut_img):
cut_gray = cv2.cvtColor(cut_img, cv2.COLOR_BGR2GRAY)
_, cut_binary = cv2.threshold(cut_gray, 127, 255, cv2.THRESH_BINARY)
# 获取边界
_, contours, hierarchy = cv2.findContours(cut_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# 获取最外层边界
contour = contours[-1]
# operator矩阵
operator = np.zeros((cut_height, cut_width))
# 根据 contour填写operator
for point in contour:
operator[point[0][1]][point[0][0]] = 1
return operator
其实这一步才是最难的,因为本人针对的是网易云盾的滑动验证码,滑动验证码会在拖拽完成之后,将交互数据发到云端。然后云端再通过机器学习反欺诈算法来检验这个交互过程是机器完成的还是人完成的。所以需要在代码中加入很多随机因子。
def auto_drag(self, distance):
element = self.browser.find_element_by_class_name("yidun_slider")
# 这里就是根据移动进行调试,计算出来的位置不是百分百正确的,加上一点偏移
#distance -= element.size.get('width') / 2
distance += 13
has_gone_dist = 0
remaining_dist = distance
#distance += randint(-10, 10)
# 按下鼠标左键
ActionChains(self.browser).click_and_hold(element).perform()
time.sleep(0.5)
while remaining_dist > 0:
ratio = remaining_dist / distance
if ratio < 0.2:
# 开始阶段移动较慢
span = random.randint(5, 8)
elif ratio > 0.8:
# 结束阶段移动较慢
span = random.randint(5, 8)
else:
# 中间部分移动快
span = random.randint(10, 16)
ActionChains(self.browser).move_by_offset(span, random.randint(-5, 5)).perform()
remaining_dist -= span
has_gone_dist += span
time.sleep(random.randint(5,20)/100)
ActionChains(self.browser).move_by_offset(remaining_dist, random.randint(-5, 5)).perform()
ActionChains(self.browser).release(on_element=element).perform()
虽然最后没能真正成功完成破解(如果很轻松的话网易爸爸也不用混了),但是过程中还是学到了有关模拟还有CV的知识。
项目代码:https://github.com/ZezhongWang/BlogCode/tree/master/selenium-%20opencv
参考链接:
https://www.v2ex.com/t/371973
https://blog.csdn.net/hjxu2016/article/details/77833336/
https://blog.csdn.net/paololiu/article/details/52514504
https://blog.csdn.net/qq_22795513/article/details/53420482
https://www.itcodemonkey.com/article/5612.html