公司要求每天需要发日报,由于每天的工作内容差异并不是很大一般都是通过导入上一篇日志进行提交,为了防止经常遗忘,使用python 做了这个小程序方便日报的提交。
大概的实现逻辑是
1、对整个日报提交流程中每一个步骤需要点击的按钮进行截图,并保存到指定目录下,将保存后的按钮按日报提交步骤进行排序
2、通过win32gui.FindWindow获取钉钉句柄,全屏打开钉钉界面
3、通过循环执行步骤的list,
a)截屏
b)查找按钮在截屏中位置坐标
c)根据坐标位置点击对应按键,每个动作之间需要增加适当延时
流程相对比较简单以下是源码
# -*- encoding: utf-8 -*-
# 钉钉句柄:StandardFrame_DingTalk
# @author qianjianfeng
import time, threading
import win32gui, win32con
import aircv as ac
from PIL import ImageGrab
import pyautogui as pag
import os
import datetime
import sys
import win32com.client
from apscheduler.schedulers.blocking import BlockingScheduler
import pythoncom
"""
[("dd_1.jpg", "C:/Users/Qian/Desktop/pythonexe/dingdingrubao/dd_1.jpg", "DATA"),
("dd_2.jpg", "C:/Users/Qian/Desktop/pythonexe/dingdingrubao/dd_2.jpg", "DATA"),
("dd_2_1.jpg", "C:/Users/Qian/Desktop/pythonexe/dingdingrubao/dd_2_1.jpg", "DATA"),
("dd_3.jpg", "C:/Users/Qian/Desktop/pythonexe/dingdingrubao/dd_3.jpg", "DATA"),
("dd_4.jpg", "C:/Users/Qian/Desktop/pythonexe/dingdingrubao/dd_4.jpg", "DATA"),
("dd_4_1.jpg", "C:/Users/Qian/Desktop/pythonexe/dingdingrubao/dd_4_1.jpg", "DATA"),
("dd_5.jpg", "C:/Users/Qian/Desktop/pythonexe/dingdingrubao/dd_5.jpg", "DATA"),
("dd_6.jpg", "C:/Users/Qian/Desktop/pythonexe/dingdingrubao/dd_6.jpg", "DATA")],
"""
# hwnd_active = win32gui.GetForegroundWindow()
# print('hwnd_active hwnd:', hwnd_active)
# print('hwnd_active text:', win32gui.GetWindowText(hwnd_active))
# print('hwnd_active class:', win32gui.GetClassName(hwnd_active))
def resource_path(relative):
if hasattr(sys, "_MEIPASS"):
return os.path.join(sys._MEIPASS, relative)
return os.path.join(relative)
# 钉钉截屏临时文件
fp = os.path.join(sys._MEIPASS)
SCREENSHORT = '%s\dd_shortscreen.jpg' % fp
print("SCREENSHORT = %s" % SCREENSHORT)
# 获取按扭坐标位置
DD_1 = resource_path(os.path.join("%s.jpg" % "dd_1"))
DD_2 = resource_path(os.path.join("%s.jpg" % "dd_2"))
DD_2_1 = resource_path(os.path.join("%s.jpg" % "dd_2_1"))
DD_3 = resource_path(os.path.join("%s.jpg" % "dd_3"))
DD_4 = resource_path(os.path.join("%s.jpg" % "dd_4"))
DD_4_1 = resource_path(os.path.join("%s.jpg" % "dd_4_1"))
DD_5 = resource_path(os.path.join("%s.jpg" % "dd_5"))
DD_6 = resource_path(os.path.join("%s.jpg" % "dd_6"))
DD_6_1 = resource_path(os.path.join("%s.jpg" % "dd_6"))
"""
root = os.getcwd()
SCREENSHORT = '%s\dd_shortscreen.jpg' % root
# 获取按扭坐标位置
DD_1 = '%s\dd_1.jpg' % root
DD_2 = '%s\dd_2.jpg' % root
DD_2_1 = '%s\dd_2_1.jpg' % root
DD_3 = '%s\dd_3.jpg' % root
DD_4 = '%s\dd_4.jpg' % root
DD_4_1 = '%s\dd_4.jpg' % root
DD_5 = '%s\dd_5.jpg' % root
DD_6 = '%s\dd_6.jpg' % root
DD_6_1 = '%s\dd_6.jpg' % root
"""
# 日报提交五个步骤
step_list = [DD_1, DD_2, DD_2_1, DD_3, DD_4, DD_4_1, DD_5, DD_6, DD_6_1]
#print(step_list)
# 计划任务时间
PLAN_HOUR = 23 # 小时
PLAN_MINUTE = 0; # 分钟
# 截屏
def screenShot(image_name):
im = ImageGrab.grab()
im.save(image_name)
# 模拟移动到对应坐标点,进行鼠标单击
def OnClick(pos):
pag.moveTo(pos[0], pos[1])
pag.click()
# 模拟移动到对应坐标点,进行键盘输入
def OnTypeInput(pos, price):
pag.moveTo(pos[0] + 10, pos[1] + 10)
pag.doubleClick()
pag.press("del")
pag.typewrite(price)
def getBtLocation(imsrc, imobj):
screenShot(SCREENSHORT)
imsrc = ac.imread(imsrc)
imobj = ac.imread(imobj)
pos = ac.find_template(imsrc, imobj)
print(pos)
circle_center_pos = pos['result']
print(circle_center_pos[0])
print(circle_center_pos[1])
return circle_center_pos
# win32gui启动钉钉
def find_window_movetop(topOrback):
pythoncom.CoInitialize()
hwnd = win32gui.FindWindow("StandardFrame_DingTalk", "钉钉")
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys('%')
win32gui.ShowWindow(hwnd, topOrback)
# win32gui.ShowWindow(hwnd, win32con.SHOW_FULLSCREEN) #显示在最前且最大化
# win32gui.ShowWindow(hwnd, win32con.SW_RESTORE) #重新显示在最前端
win32gui.SetForegroundWindow(hwnd)
rect = win32gui.GetWindowRect(hwnd)
return rect
def main():
today = datetime.datetime.now().weekday()
if today == 6:
return
find_window_movetop(win32con.SHOW_FULLSCREEN)
time.sleep(2)
for x in step_list:
try:
OnClick(getBtLocation(SCREENSHORT, x))
except Exception:
print_message(Exception)
if x == step_list[5]:
pag.scroll(-10000)
"""
if x == step_list[0]:
if win32api.GetSystemMetrics(win32con.SM_CXSCREEN) == 1366 and win32api.GetSystemMetrics(win32con.SM_CYSCREEN) == 768:
pag.scroll(-500)
"""
if x == step_list[1]:
time.sleep(12)
else:
time.sleep(10)
if os.path.exists(SCREENSHORT):
os.remove(SCREENSHORT)
find_window_movetop(win32con.HIDE_WINDOW);
def print_message(message):
print("\033[1;32m" + "#### %s ####" % message + "\033[0m")
def time_thread():
print_times()
sched = BlockingScheduler()
sched.add_job(main, 'cron', hour=PLAN_HOUR, minute=PLAN_MINUTE)
sched.start()
def print_times():
now = datetime.datetime.now()
sys.stdout.write(
"\r钉钉日报将会在每天晚上{:0>2d}:{:0>2d}自动执行发送. 当前时间 : {:0>2d}:{:0>2d}:{:0>2d}".format(
PLAN_HOUR, PLAN_MINUTE, now.hour, now.minute, now.second))
sys.stdout.flush()
t = threading.Timer(1.0, print_times)
t.start()
if __name__ == "__main__":
try:
if (sys.argv[1] != ''):
if sys.argv[1] == "now":
main()
except:
print("argv empty! start time thread")
time_thread()