概述
由于本人近期参加一个游戏比赛,然后有个拉票的环节,票高者得人气奖。又比较懒不想到处拉票麻烦别人。就想自己尝试着破解验证码然后来达到刷票的目的。
这个也纯属娱乐,最后发现是不可行的。
最终目标:实现自动点击红星,并且拖动完成验证
自动点击并且获取图片
自动模拟的过程通过 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
边缘检测计算滑动距离
计算滑动距离分为以下几步:
* 利用opencv库中提供的边界查找函数(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://github.com/ZezhongWang/BlogCode/tree/master/selenium-%20opencv>
参考链接:
https://www.v2ex.com/t/371973 <https://www.v2ex.com/t/371973>
https://blog.csdn.net/hjxu2016/article/details/77833336/
<https://blog.csdn.net/hjxu2016/article/details/77833336/>
https://blog.csdn.net/paololiu/article/details/52514504
<https://blog.csdn.net/paololiu/article/details/52514504>
https://blog.csdn.net/qq_22795513/article/details/53420482
<https://blog.csdn.net/qq_22795513/article/details/53420482>
https://www.itcodemonkey.com/article/5612.html
<https://www.itcodemonkey.com/article/5612.html>
热门工具 换一换