背景:使用selenium自动化模拟点选验证码的时候,由于直接将鼠标移动到点选点,被对方网站识别为非人为操作轨迹,因此需要从 已知两点 生成类似手动移动的鼠标轨迹。
class GenerateCurve():
'''根据两点坐标确定一条被瑟尔曲线'''
def __init__(self, point0, point1, control_point=[], point_nums=random.randint(5, 15), debug=False):
'''
:param point0: 起点
:param point1: 终点
:param control_point: 控制点
:param point_nums: 生成曲线坐标点的数量.数量越多图越凹凸不平,越少越平滑
'''
self.point0 = point0
self.point1 = point1
self.control_point = control_point
self.point_nums = point_nums
self.debug = debug
def getBezierPoints(self):
'''
:return:
'''
if not self.point_nums:
self.point_nums = random.randint(1, 6)
pointList = []
x1, y1 = int(self.point0[0]), int(self.point0[1])
x2, y2 = int(self.point1[0]), int(self.point1[1])
cx, cy = int(self.control_point[0]), int(self.control_point[1])
for i in range(self.point_nums + 1):
t = i / self.point_nums
x = math.pow(1 - t, 2) * x1 + 2 * t * (1 - t) * cx + math.pow(t, 2) * x2
y = math.pow(1 - t, 2) * y1 + 2 * t * (1 - t) * cy + math.pow(t, 2) * y2
pointList.append([int(x), int(y)])
return pointList
def getControlPoint(self):
'''
:return: 控制点
'''
if self.control_point:
return self.control_point
x0, y0 = int(self.point0[0]), int(self.point0[1])
x1, y1 = int(self.point1[0]), int(self.point1[1])
abs_x = abs(x0 - x1) / 2 # 两点横坐标相减绝对值/2
abs_y = abs(y0 - y1) / 2 # 两点横坐标相减绝对值/2
# print(abs_y)
ran_x = random.randint(0, int(abs_x)) # x取随机差值
ran_y = random.randint(0, int(abs_y)) # y取随机差值
# print(ran_x, ran_y)
self.control_point.append((x0 + x1) / 2 + random.choice([-ran_x, +ran_x]))
self.control_point.append((y0 + y1) / 2 + random.choice([-ran_y, +ran_y]))
def showRoute(self, pointList):
'''
展示曲线走势
:return:
'''
_xx = []
_yy = []
for p in pointList:
_xx.append(p[0])
_yy.append(p[1])
plt.plot(_xx, _yy, 'b-')
plt.show()
def main(self):
self.getControlPoint()
print(self.control_point)
pointList = self.getBezierPoints()
if self.debug == True:
self.showRoute(pointList)
return pointList
if __name__ == "__main__":
l = GenerateCurve([50, 268], [367, 485], [], debug=True)
l.main()
轨迹如下如图