屏幕截图小工具的制作过程问题记录 python PIL pynput pyautogui pyscreeze

  最近想做一个脚本小工具,方便写一些操作说明文档,它的功能很简单,就是把脚本打开之后,鼠标进行操作点击时,会在点击后进行截图,并在图上标记出点击的位置,有点类似于录屏软件的图片版,这样的话,如果要想用文档说明某些系统的操作步骤,就打开脚本一顿操作,操作完之后,每次步骤就自动记录下来了,带来方便。最后工具是做成了,但是中间的探索过程并不顺利,所以在这里记录一下思路和解决问题的过程。

  大体思路:鼠标左键点击,能够获取点击的坐标,并在点击之后进行屏幕截图操作,之后再用图片处理库给鼠标点击位置加上某种标记,思路很简单,开始考虑实施。

  首先这种记录工具,我第一想到的是,python+selenium 因为selenium有方便的截图功能,而且之前接触也比较多,所以可能用气来方便些,遂开始了。遇到的第一个问题,就是鼠标点击如何获取点击的位置坐标,才发现原来selenium是用代码来控制浏览器的行为,而不能监控浏览器中发生的行为,这不是它设计的初衷,所陷入困难。后来想到虽然selenium不能监控浏览器中发生的事件,但是js代码可以,所以找到了解决方案,即写一段js去监控鼠标点击的操作,之后把返回值用一个div的自定义属性在页面上保存起来,然后不断在selenium中去找这个div的属性值,直到坐标更新,再进行后续的处理。一顿调试之后,代码终于能正常返回坐标值,又处理了一些特殊情况,比如点开新的选项卡,关闭选项卡等一系列操作,用try except 捕获异常处理,最后终于能够比较健壮的返回点击的坐标。

  有了坐标,接着研究图片处理,用PIL库,思路就是,打开截图,在截图上的坐标位置画一个透明圆,重新保存,思路还是比较简单,但是画透明圆的时候遇到一点困难--明明用的是半透明的颜色,当画到图片上保存的时候,圆就不再透明了,研究了一下,最后用

Image.composite()方法解决,终于能够贴出比较完美的带透明圆的图。

  后续在调试过程中,又发现了selenium的一个不起眼的函数,driver.execute_async_script(),因为一般执行js脚本的话用driver.execute_script()执行了,后来查了一下driver.execute_async_script()的用法,发现它是异步执行的,即,能收到执行的js的返回值,且接收到返回值时才继续往下执行,否则等待30s之后报错,这样的话,我就能直接用js获取坐标传值给selenium的webdriver了,所以我去掉了中间传值用的div,精简了代码,但原来的也留了一版,以便比较性能。

  之后就开始正式测试小工具啦,从我们的后台操作开始----也是新问题的开端。登录的界面很正常,但是登进系统之后,点击界面的导航部分能够正常返回坐标,但点击屏幕主体区域并不能返回坐标值,后来研究发现,是因为页面里有iframe,而webdriver没有切换到iframe中,所以获取不到iframe中的点击坐标,但如果我切换到iframe中,又不能返回导航部分的坐标了,这个问题确实比较麻烦,想了一下看能不能用两个线程去做这件事情,即一个监控主区域的坐标,另一个进程监控iframe中的坐标?又是一顿修改,并处理同步问题,最后以失败告终,因为一个打开的浏览器驱动只对应于一个webdriver,即使有两个线程,其中一个切换到iframe上的话,另一个因为引用的同一个webdriver,所以也会去监控iframe,所以这个方法行不通。

  再后来,想到也许我应该换个思路,用selenium的话页面越复杂,代码也会越来越复杂,所以就转换了一种思路,抛弃了selenium,直接在系统层面监控鼠标的点击,后边的图片处理可以复用,顺着这个思路去查找python相关的包,发现pyHook可以实现鼠标监控,但看了下安装略复杂,心想一定有替代品,最后找到了pynput,可以完美实现鼠标监控,之后再找截图工具这个比较多,看了别人的博客比较之后发现pyautogui是不错的,所以装了这个,使用时还有个小插曲,发现pyautogui的截图功能总是报错,网上也没有相关解答,后来观察源代码发现,引入某个依赖包时报错了,导致功能不能实现,为什么报错没有深究(发现可能是因为引入包时生成的路径最后一个斜杆是反的),但自己把那段代码粘出来手动引用一次就正常了。在这个过程中又发现,原来pyautogui的截图功能完全依赖于另一个不起眼的包 pyscreeze,pyautogui的功能很强大,可以说是系统层面的selenium,能实现各种点击、输入操作,但是目前我是用到的只是它的快速截图功能,所以我不再使用pyautogui,而直接用pyscreeze去截图,结果也很完美又精简,最后一顿拼接调试,终于完成了这个截图工具的demo,代码就贴出来记录一下,用的版本是python3.5.2。

import timefrom PIL import Image, ImageDrawimport osfrom pynput import mousefrom pynput.mouse import Buttonimport pyscreeze# import pyautogui# from pyscreeze import (center, grab, locate, locateAll, locateAllOnScreen,#         locateCenterOnScreen, locateOnScreen, pixel, pixelMatchesColor,#         screenshot)

def picture_draw(path, locate):    oriImg = pyscreeze.screenshot()    # Img.save(path)    # oriImg = Image.open(path)    maskImg = Image.new(‘RGBA‘, oriImg.size, (0, 0, 0, 0))    draw = ImageDraw.Draw(maskImg)    draw.ellipse(locate, fill=(255, 255, 0, 100))

    final = Image.composite(maskImg, oriImg, maskImg)    final.save(path)

def on_move(x, y):    pass    # print(‘Pointer moved to {o}‘.format((x,y)))

i = 1def on_click(x, y, button, pressed):    global i    # button_name = ‘‘    # print(button)    if button == Button.left:        button_name = ‘Left Button‘    elif button == Button.middle:        button_name = ‘Middle Button‘    elif button == Button.right:        button_name = ‘Right Button‘    else:        button_name = ‘Unknown‘    if pressed:        if button == Button.left:            button_name = ‘Left Button‘            picture_path = os.path.abspath(‘.‘) + ‘\\picture%s.png‘ % str(i)            picture_draw(picture_path, (int(x) - 25, int(y) - 25, int(x) + 25, int(y) + 25))            i += 1        print(‘{0} Pressed at {1} at {2}‘.format(button_name, x, y))    else:        # print(‘{0} Released at {1} at {2}‘.format(button_name, x, y))        pass    if not pressed:        return False

def on_scroll(x, y, dx, dy):    # print(‘scrolled {0} at {1}‘.format(    #     ‘down‘ if dy < 0 else ‘up‘,    #     (x, y)))    pass

while True:    with mouse.Listener(no_move=on_move, on_click=on_click, on_scroll=on_scroll, suppress=False) as listener:        listener.join()

还有很多冗余和不完善代码,先留着吧,以后可能用的到,尤其是pyautogui的强大功能。 感谢大神们的博客,这段代码的主体依旧保留了你们的风格。  

  最后总结一下,这个小工具是自己在看书的时候想到的,就想来实现一下,实现过程中有很多体会,有以下3点:
1、只有熟练用好js才能使selenium的功能得到最大的发挥,那将使selenium几乎无所不能,所以如果要写自动化代码,多用一下js,既能练习一下js,又能让代码更健壮。
2、之后就是python世界的奇妙了,只要你想到的功能,都会有对应的库来支持,而且不止一个,我们要挑选那些最简单实用最多的库(pynput),而不是博客上写的最多的(pyHook)。
3、最后最大的一个感想,做这个功能,开始走了弯路,用selenium去解决,但也因此深刻体会到了“失败是成功之母”,我不是走了弯路,而是排除了一个错误选项,从而使我离真相更近,所以以后遇到问题,先不用过多的考虑哪个方案更能完美,或者担心走了弯路浪费了时间,其实浪费也不会浪费多少,尽管做就是了,不只是写程序哦。

原文地址:https://www.cnblogs.com/shuchengxiang/p/12228543.html

时间: 2024-08-27 22:53:04

屏幕截图小工具的制作过程问题记录 python PIL pynput pyautogui pyscreeze的相关文章

Windows Phone中悬浮小助手的制作过程

前言      看到过其他平台游戏中第三方sdk的一些悬浮的小助手,近来无聊,就做个玩儿,看着比较简单,做起来还是花费了不少力气. 开始 首先是页面的xaml代码,其实比较简单,就是一些Canvas里面装了些image和一个border(是作为按钮展开后的背景).下面注释的那个canvas是为了看到悬浮窗在界面右边的时的效果,方便做动画添加的,读者不用在意 要求悬浮按钮可以拖动,拖动后靠在自动屏幕边上显示,拖动的时候超过屏幕的中轴就靠在右边,点击按钮向左边以此展开按钮,如果拖动后在屏幕中轴左边则

微信小程序免费制作一键生成平台是什么原理?速成应用代理需要多少钱

微信10亿活跃用户,10亿的流量等待瓜分.想想现在人们用哪个应用最多?当然是微信,而微信小程序就是依托微信而存在的,先天优势就在那里,怎么可能不火?作为想要创业以及苦于一直没有机会发现好商机的你,为什么要错过速成应用微信小程序加盟代理这个项目? 小程序是一种不需要下载安装即可使用的应用,它实现了应用"触手可及"的梦想,用户扫一扫或者搜一下即可打开应用.也体现了"用完即走"的理念,用户不用关心是否安装太多应用的问题.应用将无处不在,随时可用,但又无需安装卸载.全面开放

[PCB制作] 1、记录一个简单的电路板的制作过程——四线二项步进电机驱动模块(L6219)

前言 现在,很多人手上都有一两个电子设备,但是却很少有人清楚其中比较关键的部分(PCB电路板)是如何制作出来的.我虽然懂点硬件,但是之前设计的简单系统都是自己在万能板上用导线自己焊接的(如下图左),复杂的都是模块拼接的(如下图右):      工作中原理图和PCB也有专门的工程师来制作,因此我对这一块了解比较少.而最近闲来无事,又因为手头上确实少一个四线二项步进电机驱动模块.起初是在淘宝上找了很久才找到一个适合的,结果实验了一下午还是不行:又考虑自己在万能板上焊接,可是发现该模块外围需要10个左

C#使用 SQLite 数据库 开发的配置过程及基本操作类,实例程序:工商银行贵金属行情查看小工具

--首发于博客园, 转载请保留此链接  博客原文地址 本文运行环境: Win7 X64, VS2010 1. SQLite 的优点: SQLite 是一款轻型数据库,开发包只有十几M, 相对于 MSSQL 几个 G 的体积来说简直是小 Case, 而且在打包成的软件里只需要添加相关的 DLL 就可以在其他的电脑运行,这一点来说比 Access 数据库还要来得方便.  SQLite虽然很小巧,但是支持的SQL语句不会太逊色于其他开源数据库. 更多详情参见百科:SQLite 2. 开发包下载 SQL

使用wxPython制作GUI小工具

我们项目客户端能看到的服务器列表由一个叫IPList.txt文本文件提供,每次启动客户端都会从CDN下载最新版本的IPList.txt.前两天运营同学那边提过来一个小工具需求,公测时对各个渠道需要提供不同的IPList.txt,如果临时加开新服或者修改老服状态(火爆/拥挤/顺畅),时间紧急手动修改容易出错,希望能有可视化工具修改. 这项工作到我手上之后,大致思索了下,决定用Python实现.用Python写过一些小工具,但没有做过GUI,查了下资料,采用了推荐比较多的wxPython库.工具逻辑

C#打包制作安装程序过程全记录

该文是根据网上的文章并结合自己实际打包的过程而整理的. 开发平台:VisualStudio2005中文版. 步骤如下: 1. 创建一个安装向导项目或安装部署项目 新建项目-〉其他项目类型-〉安装与部署-〉安装向导(或安装部署),如命名为setup. 2. 将要打包的项目导入到这个安装项目中,有两种方式:   第一种,自动方式,在解决方案上右击-〉添加-〉现有项目-〉选择你要打包的项目,这样就会把这个项目添加到该解决方案中来,   然后在安装项目setup上右击-〉添加-〉项目输出-〉主输出,在项

WordPress记录———自定义小工具自定义图片

如上图,我在WordPress中前台自定义中的小工具里设置轮播图,根据自己需求增加图片数量,添加图片时js有点问题,点击上传,选择图片之后确实显示了,但是却没有触发隐藏input的change事件,搞了好久才发现这个问题,jQuery("input[name='"+button_id+"']").trigger('change');//只有触发change事件才会更新. 自己创建的添加轮播图小工具.原本想在模板中增加的,结果技术不够,实现不了TT.下面记录下这个轮播

python制作英语翻译小工具

用python爬虫可以制作英语翻译小工具.来看下代码吧- import requests,json #函数封装 def translator(): session=requests.session() i=input('请问你要翻译什么?') url='http://fanyi.youdao.com/translate' headers={ 'Referer': 'http://fanyi.youdao.com/', 'User-Agent': 'Mozilla/5.0 (Macintosh;

Python学习之旅:用Python制作一个打字训练小工具

一.写在前面 说道程序员,你会想到什么呢?有人认为程序员象征着高薪,有人认为程序员都是死肥宅,还有人想到的则是996和 ICU. 别人眼中的程序员:飞快的敲击键盘.酷炫的切换屏幕.各种看不懂的字符代码. 然而现实中的程序员呢?对于很多程序员来说,没有百度和 Google 解决不了的问题,也没有 ctrl + c 和 ctrl + v 实现不了的功能. 那么身为一个程序员,要怎么让自己看起来更加“专业”呢?答案就是加快自己的打字速度了,敲的代码可能是错的,但这个13却是必须装的! 然而还是有不少人