用Python打造属于你的贾维斯

跟着老杨玩Python

看了复联后,各种羡慕斯塔克,成为不了钢铁侠,那就自己给自己造一个贾维斯出来吧。不仅能控制电脑,还能和我智能聊天

这是主文件,创建一个可视化的桌面,及主要业务功能

#!/usr/bin/python3
# @Time      : 2019/5/30 14:54
# @Author    : 老杨
# @FileName  : iron.py
# @Software  : PyCharm
# pip install baidu-aip
# pip install pyttsx3
# pip install requests
# http://ai.baidu.com/docs#/ASR-Online-Python-SDK/top
from tkinter import *
from aip import AipSpeech
import Recorder
import Control
import pyttsx3
import requests
import json
# pip install jsonpath
# import jsonpath
def action():
    data = entry1.get().strip()
    control = Control.Order()
    control.run(data)
rec = Recorder.Recorder()
def ok(event):
    print('开始录音')
    rec.start()
def no():
    print('结束录音')
    # 结束录音
    rec.stop()
    # 保存音频
    file = rec.save('audio')
    # 调用百度aip语音识别转义成文字
    APP_ID = '你的百度ID'
    API_KEY = '你的百度API_KEY'
    SECRET_KEY = '你的百度SECRET_KEY'
    client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
    with open(file,'rb') as fp:
            data = fp.read()
    result = client.asr(data,'wav',16000,{
        'dev_pid':1536
    })
    print(result)
    try:
        data = result['result'][0]
    except Exception as err:
        exit(err)
    return data

def voiceControl(event):
    result = no()
    print(result)
    # 提取前三位,判断是操控还是聊天
    data = result[0:3]
    order = result[3:]
    if data =='贾维斯':
        control = Control.Order()
        control.run(order)
    else:
        show(result)
# def show(content):
#     # 构造请求参数
#     request_data = {
#  "reqType":0,
#     "perception": {
#         "inputText": {
#             "text": content
#                     },
#     },
#     "userInfo": {
#         "apiKey": "d3c006b99ee94e28b6d8340f68577f02",
#         "userId": "laoYang"
#                 }
#     }
#     # 构造请求url
#     url = "http://openapi.tuling123.com/openapi/api/v2"
#     # 发送请求
#     request_data = json.dumps(request_data)
#     result = requests.post(url,request_data)
#     # 转换成json格式
#     response = json.loads(result.text)
#     # 通过jsonpath取到对应的值
#     data = jsonpath.jsonpath(response,'$..text')
#     # 语音输出
#     engine = pyttsx3.init()
#     engine.say(data)
#     engine.runAndWait()
def show(content):
    # 构造请求参数
    request_data = {
        "key":"你的图灵机器人key",
        "info":content,
        "userid":"你的图灵机器人ID"
    }
    # 构造请求url
    url = "http://www.tuling123.com/openapi/api"
    # 发送请求
    result = requests.post(url,request_data)
    # 转换格式
    response = json.loads(result.text)
    # 语音输出
    engine = pyttsx3.init()
    engine.say(response['text'])
    engine.runAndWait()
# exit()
# 实例化 创建一个GUI对象
master = Tk()
# 设置标题
master.title('贾维斯')
# 设置窗体大小以及出现在屏幕上面的位置
# 宽x高+X轴+Y轴
# 此处有坑,不是*,而是x
master.geometry('300x100+450+300')
master.resizable(False,False)
# 设置标签
# # 网格布局
Label(master,text='输入指令:',font=('黑体',18),fg='blue').grid()
# Label(master,text.txt='结果:',font=('黑体',18),fg='blue').grid(row=1,column=0)
# 设置第一个输入框
entry1 = Entry(master)
# 网格布局
entry1.grid(row=0,column=1)
button1 = Button(master,text='运行',width=10,command=action)
button1.grid(row=1,column=0)
button = Button(master,text='声控',width=10)
button.grid(row=1,column=1)
button.bind("",ok)
button.bind("",voiceControl)
# 消息循环
master.mainloop()

控制电脑的文件

#!/usr/bin/python3
# @Time      : 2019/5/25 13:07
# @Author    : 老杨
# @FileName  : Order.py
# @Software  : PyCharm
# pip install pypiwin32
# pip install pyttsx3
import os
import time
import win32api
import pyttsx3
class Order():
    def set_order(self,orderName,path):
        """
        设置指令,判断指令
        :param orderName: 指令名称
        :param path: 程序路径
        :return: None
        """
        if orderName == ''or path=='':
            raise Exception('请补充完整您的指令名称或路径')
        try:
            file = self.get_order(orderName)
            if file == None:
                self.add_order(orderName,path)
                self.tell('指令添加成功')
            else:
                self.tell('当前指令已经存在')
        except FileNotFoundError as err:
            self.tell('我是你的贾维斯')
            self.add_order(orderName,path)

    def add_order(self,orderName,path):
        """
        添加指令
        :param orderName: 指令名称
        :param path: 程序路径
        :return: None
        """
        data = orderName + '路径为->' + path + '\n'
        with open('order.txt', 'a+', encoding='utf-8') as f:
            f.write(data)
        self.tell('指令添加成功')

    def get_order(self,name,returnData='orderPath'):
        """
        根据指令,获取对应值
        :param name: 指令名称
        :param returnData:返回的结果
        :return:返回指定结果
        """
        with open('order.txt', 'r+', encoding='utf-8') as f:
            data = f.readlines()
        for key,value in enumerate(data):
            result = value.split('路径为->')
            try:
                response = dict()
                response['orderName'] = result[0].replace('\n','').strip()
                if name == response['orderName']:
                    response['orderPath'] = result[1].replace('\n','').strip()
                    response['exeName'] = response['orderPath'][response['orderPath'].rfind('\\')+1:]
                    return response[returnData]
            except TypeError as err:
                info = '第'+str(key)+'行不符合格式\n请按格式修改'
                exit(info)
                # raise Exception(info)

    # https://www.cnblogs.com/xknight/articles/1291111.html
    def startOrder(self,orderName,hwnd=0,op='open',params='',dir='',bShow=1):
        """
        根据指令,打开相应程序
        :param orderName: 指令名
        :param hwnd: 父窗口的句柄,如果没有父窗口,则为0。
        :param op: 要进行的操作,为“open”、“print”或者为空。
        :param params: 要运行的程序,或者打开的脚本。
        :param dir: 要向程序传递的参数,如果打开的为文件,则为空。
        :param bShow: 是否显示窗口。
        :return: None
        """
        file = self.get_order(orderName)
        if file != None:
            win32api.ShellExecute(hwnd,op,file,params,dir,bShow)
            self.tell('正在打开'+orderName)
        else:
            self.tell('没有找到对应的指令')
    def tell(self,data):
        """
        语音提醒
        :param data: 需要提醒的话
        :return:
        """
        engine = pyttsx3.init()
        engine.say(data)
        engine.runAndWait()
    def stopOrder(self,orderName):
        """
        关闭程序
        :param orderName: 指令名
        :return:
        """
        file = self.get_order(orderName)
        if file != None:
            res = 'TASKKILL /F /IM '+self.get_order(orderName,'exeName')
            os.system('TASKKILL /F /IM '+self.get_order(orderName,'exeName'))
            self.tell(orderName+'已经退出')
        else:
            self.tell('没有找到对应的指令')

    def run(self,orderName):
        """
        运行指令
        :param orderName: 需要执行的指令
        :return: None
        """
        if orderName=='关机':
            self.tell('即将为您关闭电脑')
            os.sys('shutdown /s /t 0')
        elif orderName=='重启':
            self.tell('即将为您重启电脑')
            os.sys('shutdown /r /t 0')
        else:
            keyWord = orderName[0:2]
            orderWord = orderName[2:]
            if keyWord == '打开':
                self.startOrder(orderWord)
            elif keyWord == '退出':
                self.stopOrder(orderWord)
            else:
                try:
                    os.sys(orderName)
                except Exception as err:
                    self.tell('请输入正确指令')

# demo 添加指令
# test = Order()
# orderName = "微信"
# path ="C:\Program Files (x86)\Tencent\WeChat\WeChat.exe"
# test.set_order(orderName,path)

实现录制音频的文件

#!/usr/bin/python3
# @Time      : 2019/5/25 13:07
# @Author    : 老杨
# @FileName  : Order.py
# @Software  : PyCharm
# pip install PyAudio
import pyaudio
import time
import threading
import wave
import os
class Recorder():
    def __init__(self, chunk=1024, bits=pyaudio.paInt16, channels=1, rate=16000):
        """
        初始设置
        :param chunk: wav文件是由若干个CHUNK组成的,CHUNK我们就理解成数据包或者数据片段
        :param format: 这个参数后面写的pyaudio.paInt16表示我们使用量化位数 16位来进行录音
        :param channels:代表的是声道,这里使用的单声道
        :param rate: 采样率16k
        :return: 生成的文件路径
        """
        self.CHUNK = chunk
        self.FORMAT = bits
        self.CHANNELS = channels
        self.RATE = rate
        self._running = True
        self._frames = []
        self._startTime = 0
        self._stopTime = 0
        self._duration = 0

    def start(self):
        """
        生成新的线程
        """
        threading._start_new_thread(self.__recording, ())

    def __recording(self):
        """
        开始录音
        """
        self._startTime = time.time()
        self._running = True
        self._frames = []
        p = pyaudio.PyAudio()
        stream = p.open(format=self.FORMAT,
                        channels=self.CHANNELS,
                        rate=self.RATE,
                        input=True,
                        frames_per_buffer=self.CHUNK)
        while (self._running):
            data = stream.read(self.CHUNK)
            self._frames.append(data)
        stream.stop_stream()
        stream.close()
        p.terminate()

    def stop(self):
        """
        停止录音
        :return: 录音时长
        """
        self._stopTime = time.time()
        self._running = False
        self._duration = int(self._stopTime-self._startTime)
        return self._duration

    def save(self, dirName,fileName=''):
        """
        保存文件
        :param fileName: 需要保存的文件路径
        :return: 生成的文件路径
        """
        p = pyaudio.PyAudio()
        if not os.path.exists(dirName):
            os.mkdir(dirName)
        if not fileName:
            fileName = time.strftime('%Y-%m-%d %H-%M-%S',time.localtime(time.time()))+".wav"
            fileName = os.path.join(dirName, fileName)
        if not fileName.endswith(".wav"):
            filename = fileName + ".wav"
            fileName = os.path.join(dirName,fileName)
        wf = wave.open(fileName, 'wb')
        wf.setnchannels(self.CHANNELS)
        wf.setsampwidth(p.get_sample_size(self.FORMAT))
        wf.setframerate(self.RATE)
        wf.writeframes(b''.join(self._frames))
        wf.close()
        return fileName

    def getDuration(self):
        """
        获取录音时长
        :return: 录音时长
        """
        return self._duration

你可能感兴趣的:(用Python打造属于你的贾维斯)