前言
近期学了用pynput模块来模拟鼠标操作,可知鼠标移动操作分为两种方式:
- 设置鼠标坐标:mouse.position = (x,y)
- 设置鼠标移动量:mouse.move(dx,dy)
在现实的人为操作中,鼠标移动轨迹不可能是直接的两点直线式移动,而是一个随机事件和距离的过程量。本例做了一个简单的测试,将鼠标的移动分为了几个小部分,每份移动距离和停留时间随机。
桌面坐标示意图:
假设人为操作中的鼠标路径是一个不回头的路径(不考虑大幅度拐弯的情况),那么假设每次移动的坐标都会介于起始和结束点为对角的矩形范围内。
方法1:控制每次鼠标的位置坐标
import random
import time
import pynput
ctr = pynput.mouse.Controller()
window_size = (1920,1080)
step = 5
target = (1366,768)#比较坐标递进
import random
import time
import pynput
ctr = pynput.mouse.Controller()
step = 5
end = (1366,768)#比较坐标递进
def compareAim(x,y):if x[0]>y[0] and x[1]> y[1]:return Trueelse:return Falsedef move_test(ctr,step,end):start = ctr.positionprint("起始坐标:",start)for i in range(0,step):var = 1while var:middle = (random.random()*end[0],random.random()*end[1])if compareAim(middle,start) and compareAim(end,middle):time.sleep(random.random()*step)start = middlebreakctr.position = middleprint("中间坐标:",middle) ctr.position = endprint("结束坐标:",end)move_test(ctr,step,end)
运行结果如下:
起始坐标: (571, 346)
中间坐标: (758.4090481030972, 412.7579005175639)
中间坐标: (879.8939462136273, 543.3225332038678)
中间坐标: (934.2595998425675, 659.5263970684135)
中间坐标: (1161.1987270599184, 744.976249523063)
中间坐标: (1218.380812975768, 749.3731512991567)
结束坐标: (1366, 768)
但是指定坐标法有一个问题就是,通过随机数生成的坐标,虽然保证了范围,但是随着步数的增加,如果前期生成的坐标已经接近终点坐标,那么程序解算难度加大。
所以可以考虑改进一下思路,比如前一半步数的坐标只在前一半的距离内。即找到一个中间点,坐标如下:
half = (end[0]-start[0],end[1]-start[1])
那么相关代码改为:
def move_test(ctr,step,end):start = ctr.positionhalf = (end[0]-start[0],end[1]-start[1])print("起始坐标:",start)for i in range(0,step):var = 1while var:if i <= step:middle = (random.random()*half[0],random.random()*half[1])else:middle = (random.random()*end[0],random.random()*end[1])if compareAim(middle,start) and compareAim(end,middle):time.sleep(random.random()*step)start = middlebreakctr.position = middleprint("中间坐标:",middle) ctr.position = endprint("结束坐标:",end)
运行结果:
起始坐标: (599, 378)
中间坐标: (678.0736112074836, 379.1899300788108)
中间坐标: (757.1533204514894, 381.7731937521009)
中间坐标: (765.0450005113754, 383.7005800701926)
中间坐标: (765.907544779111, 385.23308677811644)
中间坐标: (766.8042970123903, 388.2961359065686)
结束坐标: (1366, 768)
其实结果还是不尽人意,虽然避过了初始接近结束点,但是如果初始值接近中点,运算量依然很大。
小结:设置坐标法优于随机数的生成不确定性,很容易在步骤中出现接近结束的情况,造成运算加大。
方法2:控制每次鼠标的移动距离
ctr = pynput.mouse.Controller()
window_size = (1920,1080)
step = 10
end = (1366,768)def move_test(ctr,step,end):start = ctr.positionprint("起始坐标:",start)for i in range(0,step):if i <= step/2: dx = random.random()*(end[0]-start[0])/stepdy = random.random()*(end[1]-start[1])/stepelse:dx = random.random()*(end[0]-start[0])/step*2dy = random.random()*(end[1]-start[1])/step*2time.sleep(random.random()*0.3)ctr.move(dx,dy)print("中间坐标:",ctr.position) ctr.position = endprint("结束坐标:",end)move_test(ctr,step,end)
该方法在确定移动距离的设想是一个人在移动鼠标的过程中,从起始点到结束点的移动是先快后慢的,所以在移动距离上后半段的移动距离上限大于前半段(限定范围随机数效果好一些)
运算结果:
起始坐标: (703, 562)
中间坐标: (756, 570)
中间坐标: (769, 570)
中间坐标: (813, 576)
中间坐标: (817, 591)
中间坐标: (817, 591)
中间坐标: (840, 596)
中间坐标: (924, 605)
中间坐标: (976, 644)
中间坐标: (1000, 653)
中间坐标: (1103, 661)
结束坐标: (1366, 768)
结果表明,控制每步的移动量在解算难度要明显小一些。只是确定每步距离的方法用随机数感觉还是不够严谨。可以考虑用物理学加速度的方法来设置每步移动量,做到每步距离逐渐增大。