我心中的王者:Python-用Python控制鼠标、屏幕与键盘 本章主要说明使用Python控制鼠标、屏幕与键盘的应用。为了执行本章的程序,请安装pyaotogui模块。

我心中的王者:Python-用Python控制鼠标、屏幕与键盘

本章主要说明使用Python控制鼠标、屏幕与键盘的应用。为了执行本章的程序,请安装pyaotogui模块。

pip install pyautogui

28-1 鼠标的控制

28-1-1 提醒事项

由于这一章将讲解鼠标的控制,用户可能会因为程序设计错误造成对鼠标失去控制,造成程序无法控制,甚至无法使用鼠标结束程序,最后可能需使用下列方式结束计算机。

方法1:

Windows:同时按Ctrl + Alt +Del。

Mac OS:同时按Command + Shift + Option + Q。

方法2:

或是在设计程序时,每次启用pyautogui的方法设定暂停3秒再执行。

这时快速处理移动鼠标关闭程序。

方法3:

也可以使用下列语法先设定Python的安全防护功能失效。

首先在暂停3秒钟期间,你可以快速将鼠标光标移至屏幕左上角,这时会产生pyautogui.FailSageException异常,可以设计让程序终止。

28-1-2 屏幕坐标

我们操作鼠标时可以看到鼠标光标在屏幕上移动,对鼠标而言,屏幕坐标的基准点(0,0)位置在左上角,往右移动x轴坐标会增加,往左移动x轴坐标会减少。往下移动y轴坐标会增加,往上移动y轴坐标会减少。

坐标的单位是Pixel(像素),每一台计算机的像素可能不同,可以用size( )方法获得计算机屏幕的像素,这个方法传回2个值,分别是屏幕宽度和高度。

程序实例ch28_1.py:列出目前使用计算机的像素。

# ch28_1.py
import pyautogui
width, height = pyautogui.size() # 设定屏幕宽度和高度
print(width, height) # 打印屏幕宽度和高度

执行结果

2560 1600

由上图笔者可以得到目前所用计算机屏幕像素规格。

28-1-3 获得鼠标光标位置

在pyautogui模块内有position( )方法可以获得鼠标光标位置,这个方法会传回2个值,分别是鼠标光标的x轴和y轴坐标。

程序实例ch28_2.py:获得鼠标光标位置。

# ch28_2.py
import pyautogui
xloc, yloc = pyautogui.position() # 获得鼠标光标位置
print(xloc, yloc) # 打印鼠标光标位置

执行结果

1396 940

程序实例ch28_3.py:这个程序会持续打印鼠标光标位置,直到鼠标光标x轴位置到达1800(含)以上才停止。

ch28_3.py

import pyautogui

xloc = 0
while xloc < 1800:
xloc, yloc = pyautogui.position() # 获得鼠标光标位置
print(xloc, yloc) # 打印鼠标光标位置

执行结果 下列是部分画面。

1795 824
1795 824
1795 824
1801 824

28-1-4 绝对位置移动鼠标

在pyautogui模块内有moveTo( )方法可以将鼠标移至光标设定位置,它的使用格式如下。

moveTo(x坐标, y坐标, duration=xx) # xx是移动至此坐标的时间

程序实例ch28_4.py:控制光标在一个矩形区间移动,下列程序duration是设定光标移动至此坐标的时间,我们可以自行设定此时间。可以得到鼠标光标在左上角(300,300)、右上角(1500, 300)、右下角(1500, 700)和左下角(300, 700)间移动5次。

# ch28_4.py
import pyautogui
x, y = 300, 300
for i in range(5):
 pyautogui.moveTo(x, y, duration=0.5) # 左上角
 pyautogui.moveTo(x+1200, y, duration=0.5) # 右上角
 pyautogui.moveTo(x+1200, y+400, duration=0.5) # 右下角
 pyautogui.moveTo(x, y+400, duration=0.5) # 左下角

执行结果
鼠标自动移动

28-1-5 相对位置移动鼠标

在pyautogui模块内有moveRel( )方法可以将鼠标移至相较于前一次光标的相对位置,一般是适用在移动距离较短的情况,它的使用格式如下。

moveRel(x位移, y位移, duration=xx) # xx是移动至此坐标相对位置的时间

程序实例ch28_5.py:控制光标在一个正方形区间移动,程序执行会以光标位置为左上角,然后在正方形区间移动。程序执行期间,你将发现我们无法自主控制鼠标光标。

# ch28_5.py
import pyautogui
 
for i in range(5):
 pyautogui.moveRel(300, 0, duration=0.5) # 往右上角移动
 pyautogui.moveRel(0, 300, duration=0.5) # 往右下角移动
 pyautogui.moveRel(-300, 0, duration=0.5) # 往左下角移动
 pyautogui.moveRel(0, -300, duration=0.5) # 往左上角移动

执行结果 本程序执行结果与ch28_4.py相同。

28-1-6 键盘Ctrl-C键

如果我们现在执行ch28_3.py,可以发现除了鼠标光标在x轴超出1000像素坐标可以终止程序外,如果按下Ctrl-C键,也可以产生KeyboardInterrupt异常,造成程序终止。

了解了上述特性,我们可以改良ch28_3.py。

程序实例ch28_6.py:重新设计ch28_3.py,增加若是读者按键盘的Ctrl-C键,也可以让程序终止执行,当然要设计这类程序需借用异常处理。这个程序如果是异常结束将跳一行输出Bye字符串。

# ch28_6.py
import pyautogui
xloc = 0
print('按Ctrl-C 可以中断本程序')
try:
 while xloc < 1000:
 xloc, yloc = pyautogui.position() # 获得鼠标光标位置
 print(xloc, yloc) # 打印鼠标光标位置
except KeyboardInterrupt:
 print('\nBye')

执行结果

按Ctrl-C 可以中断本程序
2339 121

其实在教导读者时总是想一步一步引导读者,现在我们已经可以控制让键盘产生异常,让程序终止,所以设计程序已经不需要侦测限制鼠标光标所在位置,让程序终止。

程序实例ch28_7.py:重新设计ch28_6.py,让鼠标可以在所有屏幕区间移动,程序只有按Ctrl-C键才会终止。

# ch28_7.py
import pyautogui
print('按Ctrl-C 可以中断本程序')
try:
 while True:
 xloc, yloc = pyautogui.position() # 获得鼠标光标位置
 print(xloc, yloc) # 打印鼠标光标位置
except KeyboardInterrupt:
 print('\nBye')

执行结果 程序将不断显示鼠标光标位置,直至按Ctrl-C键。

2073 701
2073 701
2073 701
2073 701
Bye

28-1-7 让鼠标位置的输出在固定位置

在讲解本节功能前,笔者想先以实例介绍一个字符串的方法rjust( ),这个方法可以让字符串在设定的区间靠右输出。

程序实例ch28_8.py:设定4格空间,让数字靠右对齐输出,下列print( )函数内有str( )主要是将数字转成字符串。

# ch28_8.py
x1 = 1
x2 = 11
x3 = 111
x4 = 1111
print("x= ", str(x1).rjust(4))
print("x= ", str(x2).rjust(4))
print("x= ", str(x3).rjust(4))
print("x= ", str(x4).rjust(4))

执行结果

x= 1
x= 11
x= 111
x= 1111

相信读者应该了解了上述rjust( )的用法了,如果我们要将上述输出固定在同一行,也就是后面输出要遮盖住前面的输出,可以在print( )函数内设定输出后,不执行跳行,而是使用end=“\r”参数,\r是逸出字符,可参考3-4-3节,主要是让鼠标光标到最左位置,然后再增加flush=True。

程序实例ch28_9.py:每次输出后可以暂停1秒,下一个输出将遮盖住前一个的输出。不过这个程序在Python Shell窗口将无效,必须在DOS模式执行。

# ch28_9.py
import time, sys
x1 = 1
x2 = 11
x3 = 111
x4 = 1111
print("x= ", str(x1).rjust(4), end="\r", flush=True)
time.sleep(1)
print("x= ", str(x2).rjust(4), end="\r", flush=True)
time.sleep(1)
print("x= ", str(x3).rjust(4), end="\r", flush=True)
time.sleep(1)
print("x= ", str(x4).rjust(4), end="\r", flush=True)

执行结果 下方分别是DOS模式输出和Python Shell窗口输出的结果。

有了上述观念我们很容易设计下列观念的程序。

程序实例ch28_10.py:鼠标光标在屏幕移动,同时在固定位置输出鼠标光标的坐标。

# ch28_10.py
import pyautogui
import time
print('按Ctrl-C 可以中断本程序')
try:
 while True:
 xloc, yloc = pyautogui.position() # 获得鼠标光标位置
 xylocStr = "x= " + str(xloc).rjust(4) + " y= " + str(yloc).rjust(4)
 print(xylocStr, end="\r", flush=True) # 设定同一行最左边输出
 time.sleep(1)
except KeyboardInterrupt:
 print('\nBye')

执行结果 下方分别是DOS模式输出和Python Shell窗口输出的结果。

28-1-8 单击鼠标click( )

click( )方法主要是可以设定在目前鼠标光标位置单击,所谓的单击通常是指单击鼠标左键。基本语法如下:

click(x, y, button=‘xx') # xx是left, middle或right,预设是left

若是省略x,y,则使用目前鼠标位置单击,若不指定按哪一个键,则默认是单击鼠标右键。

程序实例ch28_11.py:让鼠标光标在(500, 450)位置产生单击的效果。

# ch28_11.py
import pyautogui
pyautogui.moveTo(500, 450)
pyautogui.click()

执行结果 由于我们没有设定任何动作,所以将只看到鼠标光标移至(500,450)。

其实也可以在click( )内增加位置参数,这时方法内容是click(x, y),这样就可以用一个click( )方法代替需使用2个方法的ch28_11.py。

程序实例ch28_12.py:在click( )内增加位置参数重新设计ch28_11.py。

# ch28_12.py
import pyautogui
pyautogui.click(500, 450)

执行结果 由于我们没有设定任何动作,所以将只看到鼠标光标移至(500,450)。

click( )函数默认是单击鼠标左键,也可以更改所按的键。

程序实例ch28_13.py:重新设计ch28_12.py,改为单击鼠标右键,在许多窗口单击鼠标右键相当于有打开快捷菜单的效果。

# ch28_13.py
import pyautogui
pyautogui.click(500, 450, button='right')

执行结果 由于笔者鼠标是在Python Shell窗口,所以可以打开快捷菜单。

28-1-9 按住与放开鼠标mouseDown( )和mouseUp( )

click( )是指单击鼠标键然后放开,其实单击鼠标键时也可以用mouseDown( )代替,放开鼠标键时可以用mouseUp( )代替。这2个方法所使用的参数意义与click( )相同。

程序实例ch28_14.py:控制在目前鼠标光标位置按着鼠标右键,1秒后,放开所按的鼠标右键,同时鼠标光标移至(800,300)位置。

# ch28_14.py
import pyautogui
import time
pyautogui.mouseDown(button='right') # 在鼠标光标位置按住鼠标右边建
time.sleep(1)
pyautogui.mouseUp(800, 300, button='right') # 放开后鼠标光标在(800, 300)

执行结果

28-1-10 拖曳鼠标

拖曳是指按着鼠标左键不放,然后移动鼠标,这个移动会在窗口画面留下轨迹,拖曳到目的位置后再放开鼠标按键。所使用的方法是dragTo( )/dragRel( ),这2个参数的使用与moveTo( )/moveRel( )相同。

有了以上观念,我们可以打开Windows系统的画图,然后绘制图形。

程序实例ch28_15.py:这个程序在执行最初有10秒钟可以选择让绘图软件变成当前工作窗口,选择画笔和颜色,完成后请让鼠标光标停留在绘图起始点。

# ch28_15.py
import pyautogui
import time
time.sleep(10) # 这10秒需要绘图窗口取得焦点,选择画笔和选择颜色
pyautogui.click() # 单击设定绘图起始点 
displacement = 10
while displacement < 300:
 pyautogui.dragRel(displacement, 0, duration=0.2)
 pyautogui.dragRel(0, displacement, duration=0.2)
 pyautogui.dragRel(-displacement, 0, duration=0.2)
 pyautogui.dragRel(0, -displacement, duration=0.2)
 displacement += 10

执行结果

28-1-11 窗口滚动scroll( )

可以使用scroll( )执行窗口的滚动,我们在Windows系统内可能打开很多窗口,这个方法会针对当前鼠标光标所在窗口执行滚动,它的语法如下:

scroll(clicks, x=”xpos”, y=”ypos”) # x,y是鼠标光标移动位置,可以省略

上述clicks是窗口滚动的单位数,单位大小会因不同平台而不同,正值是往上滚动,负值是往下滚动。如果有x,y,则先将鼠标光标移至指定位置,然后才开始滚动。

程序实例ch28_16.py:窗口滚动的应用,如果程序执行期间鼠标光标切换新的工作窗口,将造成新的窗口滚动。

# ch28_16.py
import pyautogui
import time
for i in range(1,10):
 pyautogui.scroll(30) # 往上卷动 
 time.sleep(1)
 pyautogui.scroll(-30) # 往下卷动
 time.sleep(1)

执行结果 读者可以试着切换工作窗口以体会窗口的滚动。

28-2 屏幕的处理

在pyautogui模块内有屏幕截图功能,截取屏幕图形后将产生Pillow的Image对象,可参考Pillow模块的功能,本节将分析这个实用的功能。

28-2-1 截取屏幕画面

在pyautogui模块内有screenshot( )方法,可用这个方法执行屏幕截图,屏幕截取后可以将它视为一个图像对象,所以可以使用save( )方法存储此对象,也可以直接在screenshot( )的参数中设定欲存的文件名。

程序实例ch28_17.py:截取屏幕,同时存入out28_17_1.jpg和out28_17_2.jpg。

# ch28_17.py
import pyautogui
screenImage = pyautogui.screenshot("out28_17_1.jpg") # 方法1
screenImage.save("out28_17_2.jpg") # 方法2

执行结果 下列是笔者截取屏幕画面的执行结果。

28-2-2 裁切屏幕图形

我们可以参考前一章的crop( )方法裁切屏幕图形,此方法的参数是一个定义裁切画面区间的元组。

程序实例ch28_18.py:裁切屏幕图形,下列是笔者屏幕的执行结果。

# ch28_18.py
import pyautogui
screenImage = pyautogui.screenshot()
cropPict = screenImage.crop((960,210,1900,480))
cropPict.save("out28_18.jpg")

执行结果

28-2-3 获得图像某位置的像素色彩

可以使用getpixel((x,y))获得x,y坐标的像素色彩,由于屏幕截图完全没有透明,所以所获得的是RGB的色彩元组。

程序实例ch28_19.py:列出固定位置的RGB色彩元组。

# ch28_19.py
import pyautogui
screenImage = pyautogui.screenshot()
x, y = 200, 200
print(screenImage.getpixel((x,y)))

执行结果 下列是笔者屏幕的执行结果,读者屏幕可能有不一样的结果。

(24, 24, 24)

28-2-4 色彩的比对

有时候我们可能需要确定某一个像素坐标的色彩是否是某种颜色,这时可以使用色彩比对功能pixelMatchesColor( ),它的语法格式如下:

boolean = pyautogui.pixelMatchesColor(x,y,(Rxx,Gxx,Bxx))

上述x,y参数是坐标,会将此坐标的色彩取回,然后和第2个参数的色彩比对,如果相同则返回True,否则返回False。

程序实例ch28_20.py:像素色彩比对的应用,读者计算机可能会有不一样的结果。

# ch28_20.py
import pyautogui
x, y = 200, 200
trueFalse = pyautogui.pixelMatchesColor(x,y,(255,255,255))
print(trueFalse)
trueFalse = pyautogui.pixelMatchesColor(x,y,(0,0,255))
print(trueFalse)

执行结果

False
False

28-3 使用Python控制键盘

我们也可以利用pyautogui模块对键盘做一些控制。

28-3-1 基本传送文字

pyautogui模块内有typewrite( )方法,可以对目前焦点窗口传送文字,不过经笔者测试这个功能目前无法传送中文字。

程序实例ch28_21.py:请在10秒之内打开一个新的记事本编辑窗口,将输入环境设为英文输入,同时设为当前焦点窗口,这个程序会在此窗口输入“Ming-Chi Institute of Technology”。

# ch28_21.py
import pyautogui
import time
print("请在10秒内开启记事本并设为焦点窗口")
time.sleep(10)
pyautogui.typewrite('Ming-Chi Institute of Technology')

执行结果

typewrite( )函数的参数是要传输的字符串,我们也可以增加第2个参数,所增加的参数是数字,代表相隔多少秒输出一个字符。

程序实例ch28_22.py:重新设计ch28_11.py,输出相同字符串,但是每隔0.1秒输出一个字母。

# ch28_22.py
import pyautogui
import time
print("请在10秒内开启记事本并设为焦点窗口")
time.sleep(10)
pyautogui.typewrite('Ming-Chi Institute of Technology', 0.1)

执行结果 每隔0.1秒输出一个字母,最后结果与ch28_21.py相同。

28-3-2 键盘按键名称

我们也可以使用输入单一字符方式执行键盘数据的输入,此时typewrite( )的第一个参数是字符列表。

程序实例ch28_23.py:每隔1秒输入一个英文字符。

# ch28_23.py
import pyautogui
import time
print("请在10秒内开启记事本并设为焦点窗口")
time.sleep(10)
pyautogui.typewrite(['M', 'i', 'n', 'g'], 1)

执行结果

有些键盘是具有特殊功能的,例如,backspace应如何使用Python表达,光标左移应如何使用Python表达?在pyautogui.KEYBOARD_KEYS列表有完整说明,下列是使用相同名称英文的列表。

下列是比较特殊的Python输入与意义表。

程序实例ch28_24.py:使用特殊按键输出字符串“Ming”,由于每隔1秒才输出一个字符,所以读者可以注意它的执行变化。

# ch28_24.py
import pyautogui
import time
print("请在10秒内开启记事本并设为焦点窗口")
time.sleep(10)
pyautogui.typewrite(['M', 'i', 'm', 'g', 'left', 'left', 'del', 'n'], 1)

执行结果

程序实例ch28_25.py:使用Python控制键盘输入,同时让光标在不同行间执行工作。第一行输出笔者故意输入错误,第二行则去修改第一行的错误。

# ch28_25.py
import pyautogui
import time
print("请在10秒内开启记事本并设为焦点窗口")
time.sleep(10)
pyautogui.typewrite(['M', 'i', 'n', 'k', 'enter'], 1)
pyautogui.typewrite(['M', 'i', 'n', 'g', 'up', 'backspace', 'g'], 1)

执行结果

28-3-3 按下与放开按键

在pyautogui模块中keyDown( )是按下键盘按键同时不放开按键,keyUp( )是放开所按的键盘按键。keyPress( )则是按下并放开。

程序实例ch28_26.py:这个程序会输出“*”字符和打开记事本的帮助菜单。

# ch28_26.py
import pyautogui
import time
print("请在10秒内开启记事本并设为焦点窗口")
time.sleep(10)
# 以下输出*
pyautogui.keyDown('shift')
pyautogui.press('8')
pyautogui.keyUp('shift')
# 以下开启说明菜单
pyautogui.keyDown('alt')
pyautogui.press('H')
pyautogui.keyUp('alt')

执行结果

28-3-4 快速组合键

在pyautogui模块中hotkey( )可以用于按键的组合,下列将直接以实例说明。

程序实例ch28_27.py:使用hotkey( )重新设计ch28_26.py。

# ch28_27.py
import pyautogui
import time
print("请在10秒内开启记事本并设为焦点窗口")
time.sleep(10)
pyautogui.hotkey('shift', '8') # 输出*
pyautogui.hotkey('alt', 'H') # 开启说明菜单

执行结果 与ch28_26.py相同。

28-4 网络窗体的填写

当我们使用Python可以控制鼠标、键盘和屏幕后,其实就可以利用键盘执行网络窗体的输入了,这一节笔者将以实例说明网络窗体的输入。请进入下列网站:

http://www.siliconstone.com

这是国外著名国际认证公司的网址,笔者将以此为实例说明如何利用Python填写窗体,然后点选Sign in/Sign up。

将看到下列画面:

请单击Create a new account。


请点选中国-简体中文,然后可以看到下列窗体。

程序实例ch28_28.py:这个窗体有许多字段,笔者将以实例说明输入字段实例。注意:由于无法输入中文,所以程序以输入英文取代。

# ch28_28.py
import pyautogui
import time
print("请在10秒内开启记事本并设为焦点窗口")
time.sleep(10)
pyautogui.typewrite('Taiwan\t') # Taiwan
pyautogui.typewrite('Hung\t') # 姓
pyautogui.typewrite('Jiin-Kwei\t') # 名
pyautogui.typewrite('Jiin-Kwei\t') # 名
pyautogui.typewrite('Hung\t') # 姓
pyautogui.typewrite('1975\t') # 出生年 
pyautogui.typewrite('01\t') # 月
pyautogui.typewrite('01\t') # 日
pyautogui.typewrite('\t') # 选男生
pyautogui.typewrite('Ming-Chi Inst. of Tech\t') # 学校
pyautogui.typewrite('Deartment of ME') # 科系

执行结果 首先程序执行时操作系统需在英文输入模式下,然后有10秒钟可以点选国籍字段,请将鼠标光标放在此字段。

未来程序将可以自动填写下列窗体。

上述程序设计是将给10秒执行启动网页窗体为焦点窗口,将鼠标光标移至第一个字段,再执行输入。另一种方式是将窗口放到最大,先侦测第一个字段的屏幕坐标,再将鼠标光标移至此字段,然后执行输入。上述是只填写一个表单,我们可以将所要填写的数据以字典列表存储,然后用循环填写。

由于Python可以控制窗体的输入,这也代表黑客可以利用循环不断更改输入账号(记住:笔者在ch18_11.py曾经设计暴力解密码程序),同时更改密码方式攻击网站,特别是金融机构网站,当然一般要求输入账号的网站也很容易受到攻击。所以目前一般网站为了防止黑客利用此特性会要求使用者输入确认码,这样黑客就无法使用程序(我们又称机器人)连续进入系统测试账号。下列是2个不同单位所谓的账号确认码画面。

科技的隐忧,现在文字识别功能已经变得很容易,所以上述验证码,其实也可以利用程序处理,所以有些更加严谨的机构在设计确认码时,会将数字设计得很奇怪,虽有好处,但是常常真正用户看不清楚数字造成困扰,所以是两难。所以现在金融机构处理个人网络银行登录时,除了用户身份证号还会增加用户名和密码,主要是防黑客攻击。

作者:andyyah晓波原文地址:https://blog.csdn.net/andyyah/article/details/140868742

%s 个评论

要回复文章请先登录注册