每天早上来面对着满屏幕的程序,有时候可能要找半天才能找到我们想要的,这样不仅耽误了工作效率,还会引起我们眼睛的疲劳,而且中午吃饭的时候我们常常不能按时去,这样会影响我们的身体,到了晚上下班的时候,我们可能常常忘记打卡,这就会导致我们的考勤有问题。
那么这个时候我们就需要一款办公助手了,下面我们来动手用程序实践一下。
程序所需要的环境及依赖
- mac
- python
- curses
- os
- pyttsx3 文字转语音
- subprocess
- PyQt5 创建UI
程序助手
为了解决我们一大早面对这么多程序的烦恼,精准的帮我们找到想要打开的程序,那么我们就需要这个程序助手了。
下面是程序截图
我们按下对应的键盘,就可以快速帮我们打开程序。
以下是代码
start.py
import curses
from curses import panel
import time
from task import Task
import os
import pyttsx3
class Menu(object):
def __init__(self, items, stdscreen):
self.window = stdscreen.subwin(0, 0)
self.window.keypad(1)
self.panel = panel.new_panel(self.window)
self.panel.hide()
panel.update_panels()
self.position = 0
self.items = items
self.items.append(('exit', 'exit'))
self.task = Task()
def navigate(self, n):
self.position += n
if self.position < 0:
self.position = 0
elif self.position >= len(self.items):
self.position = len(self.items)-1
def display(self):
self.panel.top()
self.panel.show()
self.window.clear()
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
self.window.addstr(5, 20,'Robot Sallen为您服务\n', curses.color_pair(1))
while True:
self.window.refresh()
curses.doupdate()
for index, item in enumerate(self.items):
if index == self.position:
mode = curses.color_pair(1)
else:
mode = curses.A_NORMAL
msg = '%d. %s' % (index, item[0])
self.window.addstr(8+index, 21, msg,mode )
key = self.window.getch()
if key in [curses.KEY_ENTER, ord('\n')]:
if self.position == len(self.items)-1:
break
else:
self.items[self.position][1]()
elif key == curses.KEY_UP:
self.navigate(-1)
elif key == curses.KEY_DOWN:
self.navigate(1)
self.task.handle_task(key)
self.window.clear()
self.panel.hide()
panel.update_panels()
curses.doupdate()
class MyApp(object):
def __init__(self, stdscreen):
self.screen = stdscreen
curses.curs_set(0)
submenu_items = [
('打开微信', curses.beep),
('打开Markdown', curses.flash),
('听QQ音乐', curses.beep),
('听网易云', curses.flash),
('打开VSCode', curses.beep),
('打开Wechat Tool', curses.flash),
('浏览掘金', curses.beep)
]
submenu = Menu(submenu_items, self.screen)
main_menu_items = [
('打开微信', curses.beep),
('打开Markdown', curses.flash),
('听QQ音乐', curses.beep),
('听网易云', curses.flash),
('打开VSCode', curses.beep),
('打开Wechat Tool', curses.flash),
('浏览掘金', curses.beep)
]
main_menu = Menu(main_menu_items, self.screen)
main_menu.display()
if __name__ == '__main__':
curses.wrapper(MyApp)
task.py
import os
class Task(object):
def __init__(self):
self.command_dict = {
ord('0'):"open /Applications/WeChat.app",
ord('1'):"open /Applications/Typora.app",
ord('2'):"open /Applications/QQMusic.app",
ord('3'):"open /Applications/NeteaseMusic.app",
ord('4'):"open https://juejin.cn",
ord('5'):"open /Applications/Visual\ Studio\ Code.app",
ord('6'):"open /Applications/wechatwebdevtools.app",
}
def handle_task(self,key):
if key == ord('7'):
exit()
else:
os.system(self.command_dict.get(key))
吃饭提醒/下班提醒
有时候我们忙着的时候,中午吃饭常常不按点,这对我们的身体不好,所以我们就需要一个提醒吃饭助手,当中午12点时候,我们的电脑将会提醒我们吃饭,话不多说,上代码。
同样的我们下班可能也常常忘记打卡,那么我们就需要一个提醒打卡的工具。为了避免我们忘记,程序会在电脑屏幕弹出一个框,让我们确认打卡。
核心代码:
import time
from apscheduler.schedulers.background import BackgroundScheduler
import os
import pyttsx3
from subprocess import call
def job():
sys_time = time.strftime('%H:%M', time.localtime(time.time()))
eat_time = '12:00'
off_work_time = '18:00'
if sys_time == eat_time:
# 播放吃饭声音
os.system("python3 xxxxx.py") # xxx.py为吃饭声音py文件
if sys_time == off_work_time:
# 播放下班声音
os.system("python3 xxxxx.py") # xxx.py为下班声音py文件
time.sleep(1)
# 打开强制打卡框
os.system("python3 xxxxx.py") # xxx.py为打开UIpy文件
if __name__ == '__main__':
# 调大系统音量
# call(["osascript -e 'set volume output volume 80'"], shell=True)
# BackgroundScheduler: 适合于要求任何在程序后台运行的情况,当希望调度器在应用后台执行时使用。
scheduler = BackgroundScheduler()
# 采用非阻塞的方式
# 采用固定时间间隔(interval)的方式,每隔3秒钟执行一次
scheduler.add_job(job, 'interval', seconds=3)
# 这是一个独立的线程
scheduler.start()
while True:
time.sleep(2)
播放声音的文件
import pyttsx3
if __name__ == '__main__':
engine = pyttsx3.init()
engine.say("下班了记得打卡 下班了记得打卡 下班了记得打卡")
engine.runAndWait()
打卡UI样式及文件
UI代码文件:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox,QPushButton,QDesktopWidget,QLabel
import os
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def initUI(self):
self.resize(250, 150)
self.center()
self.setWindowTitle('这是一个提示')
self.label_1=QLabel(self)
self.label_1.setText("<a style='color:green'>下班了该打卡了!</a>")
self.label_1.setAutoFillBackground(True)
self.label_1.move(80, 50)
self.show()
def closeEvent(self, event):
reply = QMessageBox.question(self, '信息', '确认已经打卡了吗?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
event.accept()
else:
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
优化
因为都是python脚本,所以每次需要打开几个文件也比较麻烦,逼格也不够高,那么我们继续优化。 通过语音识别指定关键字:我的是robot sallen,从而打开我们这几个脚本。以下是代码。
# -*- coding: utf-8 -*-
import pyttsx3
import sys
import json
import time
import speech_recognition as sr
import os
import requests
from subprocess import call
IS_PY3 = sys.version_info.major == 3
if IS_PY3:
from urllib.request import urlopen
from urllib.request import Request
from urllib.error import URLError
from urllib.parse import urlencode
timer = time.perf_counter
else:
import urllib2
from urllib2 import urlopen
from urllib2 import Request
from urllib2 import URLError
from urllib import urlencode
if sys.platform == "win32":
timer = time.clock
else:
# On most other platforms the best timer is time.time()
timer = time.time
API_KEY = ''
SECRET_KEY = ''
# 需要识别的文件
AUDIO_FILE = './recording.wav' # 只支持 pcm/wav/amr 格式,极速版额外支持m4a 格式
# 文件格式
FORMAT = AUDIO_FILE[-3:]; # 文件后缀只支持 pcm/wav/amr 格式,极速版额外支持m4a 格式
CUID = '123456PYTHON';
# 采样率
RATE = 16000; # 固定值
# 普通版
DEV_PID = 1737; # 1537 表示识别普通话,使用输入法模型。1536表示识别普通话,使用搜索模型。根据文档填写PID,选择语言及识别模型
ASR_URL = 'http://vop.baidu.com/server_api'
SCOPE = 'audio_voice_assistant_get' # 有此scope表示有asr能力,没有请在网页里勾选,非常旧的应用可能没有
# 极速版
class DemoError(Exception):
pass
""" TOKEN start """
TOKEN_URL = 'http://openapi.baidu.com/oauth/2.0/token'
def fetch_token():
params = {'grant_type': 'client_credentials',
'client_id': API_KEY,
'client_secret': SECRET_KEY}
post_data = urlencode(params)
if (IS_PY3):
post_data = post_data.encode('utf-8')
req = Request(TOKEN_URL, post_data)
try:
f = urlopen(req)
result_str = f.read()
except URLError as err:
# print('token http response http code : ' + str(err.code))
result_str = err.read()
if (IS_PY3):
result_str = result_str.decode()
# print(result_str)
result = json.loads(result_str)
# print(result)
if ('access_token' in result.keys() and 'scope' in result.keys()):
if SCOPE and (not SCOPE in result['scope'].split(' ')): # SCOPE = False 忽略检查
raise DemoError('scope is not correct')
# print('SUCCESS WITH TOKEN: %s ; EXPIRES IN SECONDS: %s' % (result['access_token'], result['expires_in']))
return result['access_token']
else:
raise DemoError('MAYBE API_KEY or SECRET_KEY not correct: access_token or scope not found in token response')
def rec(rate=16000):
r = sr.Recognizer()
with sr.Microphone(sample_rate=rate) as source:
print("please say something")
audio = r.listen(source)
with open("recording.wav", "wb") as f:
f.write(audio.get_wav_data())
""" TOKEN end """
def begin():
token = fetch_token()
rec()
speech_data = []
with open(AUDIO_FILE, 'rb') as speech_file:
speech_data = speech_file.read()
length = len(speech_data)
if length == 0:
raise DemoError('file %s length read 0 bytes' % AUDIO_FILE)
params = {'cuid': CUID, 'token': token, 'dev_pid': DEV_PID}
#测试自训练平台需要打开以下信息
params_query = urlencode(params);
headers = {
'Content-Type': 'audio/' + FORMAT + '; rate=' + str(RATE),
'Content-Length': length
}
url = ASR_URL + "?" + params_query
# print post_data
req = Request(ASR_URL + "?" + params_query, speech_data, headers)
try:
begin = timer()
f = urlopen(req)
result_str = f.read()
except URLError as err:
result_str = err.read()
if (IS_PY3):
result_str = str(result_str)
record_res = json.loads(result_str)
record_str = record_res['result'][-1]
sheet = ['hi robot sallen']
if (record_str in sheet):
# 打开程序助手
# 打开吃饭助手
# ...
if __name__ == '__main__':
begin()
运行这个脚本,就像我们平时用小爱同学一样,hi robot sallen,我们对着电脑说出关键字即可,通过百度识别出对应的文字信息,进行匹配。从而执行程序打开步骤。
更多思路
-
由于程序助手,打开文件的程序都是我们预先录入常用的,所以存在易用问题,我们可以通过检测项目进度、或者任务的方式,智能排列我们的程序组合,而不是预先固定录入。
-
由于每天都需要启动脚本,那么也是一件麻烦的事,同样的我们也可以利用mac 定时任务,每天早上帮我们执行脚本。
同名公众号
欢迎关注同名公众号,获取更多资源。人工智能、机器学习、计算机视觉等文章分享。干货实战技巧,一起精进技术。