Python 智能语音机器人(改进版)

news/2024/10/30 15:30:12/

本篇为改进版,之前部分代码存在错误,部分网站api也已经失效,现在更换api,并对部分代码进行重写。

本次在Pycharm上测试
相关模块如下:

baidu-aip==4.16.11
beautifulsoup4==4.12.2
chardet==5.1.0
lxml==4.9.2
PyAudio==0.2.13
pycryptodome==3.18.0
pygame==2.4.0
pyttsx3==2.90
requests==2.31.0
wxPython==4.2.1

废话不多说,先上效果图

在这里插入图片描述

功能一:人机互动

在这里插入图片描述

功能二:播放音乐

在这里插入图片描述

功能三:天气

在这里插入图片描述

功能四:一句话新闻

在这里插入图片描述

把以下参数更换成你自己的

# 百度需要的参数
APP_ID = '000000'
API_KEY = 'xxxxxx'
SECRET_KEY = 'xxxxxx'
# 图灵机器人需要的参数
tuling_apiKey = "xxxxxx"
tuling_userId = "000000"
# 易客云需要的参数
yikeyun_appid = '000000'
yikeyun_appsecret = 'xxxxxx'

易客云平台(https://yikeapi.com/account)
请添加图片描述

图灵机器人
http://www.tuling123.com/member/robot/index.jhtml
请添加图片描述

百度语音识别api 介绍请看
https://ai.baidu.com/tech/speech?_=1687103124997

控制台:
https://console.bce.baidu.com/ai/?fromai=1#/ai/speech/overview/index
在这里插入图片描述
按照这些步骤一步一步创建自己的应用,完成个人实名认证可以有一定的免费使用量,创建应用完成后,从”我的应用“ 即可看到相应的userid, apikey 等。


import pyaudio
import wave
import win32com.client
from aip import AipSpeech
import base64
import random
from binascii import hexlify
from Crypto.Cipher import AES
import json
import time
import wx
import pyttsx3
import requests
from bs4 import BeautifulSoup
import chardet
import pygame
import win32com.client# 百度需要的参数
APP_ID = '000000'
API_KEY = 'xxxxxx'
SECRET_KEY = 'xxxxxx'
# 图灵机器人需要的参数
tuling_apiKey = "xxxxxx"
tuling_userId = "000000"
# 易客云需要的参数
yikeyun_appid = '000000'
yikeyun_appsecret = 'xxxxxx'speaker = win32com.client.Dispatch("SAPI.SpVoice")
def record(file_path):# 各路参数CHUNK = 1024FORMAT = pyaudio.paInt16CHANNELS = 1RATE = 16000RECORD_SECONDS = 5WAVE_OUTPUT_FILENAME = file_pathpau = pyaudio.PyAudio()stream = pau.open(format=FORMAT,channels=CHANNELS,rate=RATE,input=True,frames_per_buffer=CHUNK, )frames = []print("开始录音")speaker.Speak("开始录音")for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):data = stream.read(CHUNK)frames.append(data)print("录音结束")speaker.Speak("录音结束")stream.stop_stream()stream.close()pau.terminate()wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')wf.setnchannels(CHANNELS)wf.setsampwidth(pau.get_sample_size(FORMAT))wf.setframerate(RATE)wf.writeframes(b''.join(frames))wf.close()
def voice2text(APP_ID, API_KEY, SECRET_KEY, file_path):client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)ret = client.asr(get_data(file_path), 'pcm', 16000, {'dev_pid': 1536}, )return ret['result']
def get_data(file_path):with open(file_path, 'rb') as fp:return fp.read()#人机互动
engine = pyttsx3.init()
# 向api发送请求
def get_response(msg):apiUrl  ='http://openapi.turingapi.com/openapi/api/v2'data = {"reqType": 0,"perception": {"inputText": {"text":  msg},},"selfInfo": {"location": {"city": "北京","province": "北京","street": "信息路"}},"userInfo": {"apiKey": tuling_apiKey,"userId": tuling_userId,}}try:data = json.dumps(data)r = requests.post(apiUrl, data=data).json()res = r['results'][0]['values']['text']print(res)engine.say(res)engine.runAndWait()except:returndef say():global chat_message# 存放的文件名称file_path = "./data/chat-audio.wav"# 先调用录音函数record(file_path)# 语音转成文字的内容chat_message = voice2text(APP_ID, API_KEY, SECRET_KEY, file_path)print(chat_message)def chatwithrobot():i=0while i<5:say()get_response(chat_message)i=i+1print("5次对话已经结束!")#音乐播放class GetMusic:def __init__(self):self.key = GetParamsAndEncSecKey()self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36','Referer': 'http://music.163.com/'}self.session = requests.Session()self.session.headers = self.headersself.conmment_url = 'https://music.163.com/weapi/v1/resource/comments/R_SO_4_{}?csrf_token='  # 评论self.lyric_url = 'https://music.163.com/weapi/song/lyric?csrf_token='  # 歌词self.music_url = 'https://music.163.com/weapi/song/enhance/player/url?csrf_token='  # 歌曲self.url = 'https://music.163.com/weapi/cloudsearch/get/web?csrf_token='  # 搜索歌曲列表,无歌曲链接def get_params_and_encSecKey(self, song=None):'''获取什么就返回所需要两个参数1. 歌曲2. 歌词3. 评论  默认4. 搜索的歌曲列表:param song::return:'''if isinstance(song, int):data = {"ids": [song], "br": 128000, "csrf_token": ""}elif isinstance(song, str) and song.isdigit():data = {"id": song, "lv": -1, "tv": -1, "csrf_token": ""}elif song == None:data = {}else:data = {"hlpretag": "<span class=\"s-fc7\">", "hlposttag": "</span>", "s": song, "type": "1", "offset": "0","total": "true", "limit": "30", "csrf_token": ""}song = json.dumps(data)data = self.key.get(song)return datadef get_music_list_info(self, name):'''获取歌曲详情:歌名+歌曲id+作者:param name::return:'''data = self.get_params_and_encSecKey(name)res = self.session.post(self.url, data=data)  # 歌曲song_info = res.json()['result']['songs']for song in song_info:song_name = song['name']song_id = song['id']songer = song['ar'][0]['name']print(song_name, '\t', song_id, '\t', songer)global SongName  # 定义为全局变量global SongId  # 定义为全局变量global Songer  # 定义为全局变量SongName=song_nameSongId=song_idSonger=songerself.get_music_url(song_id)self.get_music_lyric(song_id)self.get_music_comment(song_id)breakdef get_music_url(self, id):'''获取歌曲URL链接:param id::return:'''global Song_url  # 定义为全局变量data = self.get_params_and_encSecKey(id)res = self.session.post(self.music_url, data=data)song_url = res.json()['data'][0]['url']Song_url=song_url#print(song_url)def get_music_lyric(self, id_str):'''获取歌词:param id_str::return:'''data = self.get_params_and_encSecKey(str(id_str))res = self.session.post(self.lyric_url, data=data)lyric = res.json()['lrc']['lyric']#print(lyric)def get_music_comment(self, song_id):'''获取歌曲评论: 评论人+内容+头像:param song_id::return:'''data = self.get_params_and_encSecKey()comment = self.session.post(self.conmment_url.format(str(song_id)), data=data)com_list = comment.json()['hotComments']for com in com_list:content = com['content']nickname = com['user']['nickname']user_img = com['user']['avatarUrl']#print(nickname, '!!!!' + content + '!!!!', user_img)
class GetParamsAndEncSecKey:def __init__(self):self.txt = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'self.i = ''.join(random.sample(self.txt, 16))  # 16为随机数self.first_key = '0CoJUm6Qyw8W8jud'def get(self, song):'''获取加密的参数params是两次加密的:param song::return:'''res = self.get_params(song, self.first_key)params = self.get_params(res, self.i)encSecKey = self.get_encSecKey()return {'params': params,'encSecKey': encSecKey}def get_params(self, data, key):'''获得params,加密字符长度要是16的倍数:param data::param key::return:'''iv = '0102030405060708'num = 16 - len(data) % 16data = data + num * chr(num)  # 补足cipher = AES.new(key.encode(), AES.MODE_CBC, iv.encode())result = cipher.encrypt(data.encode())result_str = base64.b64encode(result).decode('utf-8')return result_strdef get_encSecKey(self):'''获取encSecKey,256个字符串hexlify--->转换为btyes类型pow--->两个参数是幂,三个参数是先幂在取余format(rs, 'x').zfill(256)-->256位的16进制:return:'''enc_key = '010001'modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'rs = pow(int(hexlify(self.i[::-1].encode('utf-8')), 16), int(enc_key, 16), int(modulus, 16))return format(rs, 'x').zfill(256)
def music():file_path="./data/music.wav"# 先调用录音函数record(file_path)# 语音转成文字的内容song_message = voice2text(APP_ID, API_KEY, SECRET_KEY, file_path)print(song_message)song_name = song_message[0].split('播放')[1]Msuic = GetMusic()Msuic.get_music_list_info(song_name)songid=str(SongId)headers = { 'User-agent':'Mozilla/5.0 (X11; Linux x86_64; rv:57.0)Gecko/20100101 Firefox/57.0',}response = requests.get("http://music.163.com/song/media/outer/url?id=" + songid + ".mp3",headers = headers)content = response.contentwith open('./data/'+SongName+'.mp3', mode = "wb") as f:f.write(content)print(SongName + "  " + "下载完成")engine = pyttsx3.init()engine.say("即将为您播放 "+Songer+' 的 '+SongName)engine.runAndWait()pygame.mixer.init()filename = './data/' + SongName+'.mp3'pygame.mixer.music.load(filename)pygame.mixer.music.play()#天气播报
def weather():# 存放的文件名称file_path='./data/weather-audio.wav'# 先调用录音函数record(file_path)# 语音转成文字的内容weather_message =voice2text(APP_ID, API_KEY, SECRET_KEY, file_path)print(weather_message)#抓取中国天气网指定城主天气#input_message=['播放杭州天气情况']input2=''.join(weather_message)  #转换成字符串city_name=input2[2:4]s1 = f'https://v0.yiketianqi.com/api?unescape=1&version=v61&appid={yikeyun_appid}&appsecret={yikeyun_appsecret}&city='url=s1+city_name  #拼接 urlr = requests.get(url)r.encoding = 'utf-8'# 提取相关天气信息date=r.json()["date"]templow=r.json()["tem2"]temphigh=r.json()["tem1"]tempnow=r.json()["tem"]week=r.json()["week"]tip=r.json()["air_tips"]weather=r.json()['wea_day']add=r.json()["city"]wind=r.json()['win']WS=r.json()["win_speed"]t = time.localtime() # 当前时间的纪元值fmt = "%H %M"now = time.strftime(fmt, t) # 将纪元值转化为包含时、分的字符串now = now.split(' ') #以空格切割,将时、分放入名为now的列表中hour = now[0]minute = now[1]wea='你好,今天是%s%s,现在北京时间%s时%s分,%s天气 %s,气温%s摄氏度~%s摄氏度,现在为%s摄氏度,%s,风力%s,%s'%(date,week,hour,minute,add,weather,templow,temphigh,tempnow,wind,WS,tip)print(wea)engine = pyttsx3.init()engine.say('即将为您播放'+city_name+"天气情况")engine.say(wea)engine.runAndWait()#新闻播报
def news():def get_content():url="https://news.topurl.cn/" # 爬取一名话新闻网科技类新闻headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}rqg=requests.get(url,headers=headers) # 开始爬取,设置headers信息来伪装成浏览器请求数据rqg.encoding=chardet.detect(rqg.content)['encoding']html=rqg.content.decode('utf-8') #换化编码为utf-8soup=BeautifulSoup(html,'lxml')soup.prettify() #格式化soup对象return soupsoup2=get_content()target=soup2.find_all(class_='news-wrap') #取新闻标题Tag=[]for tag in target:Tag.append(tag.get_text())  #取新闻标题文本添加到列表中list_news = Tag[0].replace('\n', '').split('\u2003')list_news.pop() # 删除最后一个空项engine = pyttsx3.init()engine.say('即将为您播放新闻')engine.runAndWait()for news in list_news:print(news)engine.say(news)engine.runAndWait()#GUI界面speaker = win32com.client.Dispatch("SAPI.SpVoice")
class Panel1(wx.Panel):"""class Panel1 creates a panel with an image on it, inherits wx.Panel"""def __init__(self, parent, id):# create the panelwx.Panel.__init__(self, parent,id)try:image_file = './image/bg.png'bmp1 = wx.Image(image_file, wx.BITMAP_TYPE_ANY).ConvertToBitmap()self.bitmap1 = wx.StaticBitmap(self, -1, bmp1, (0, 0))except IOError:print ("Image file is not found") % image_fileraise SystemExitpic1 = wx.Image("./image/hudong.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()pic2 = wx.Image("./image/yinyue.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()pic3 = wx.Image("./image/tianqiqing.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()pic4 = wx.Image("./image/xinwen.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()#绘图按钮1,默认风格3Dself.button1 = wx.BitmapButton(self.bitmap1, -1, pic1, pos = (230, 420),style=0,size=(50,50))self.Bind(wx.EVT_BUTTON, self.On1Click, self.button1)self.button1.SetDefault()#绘图按钮2,默认风格3Dself.button2 = wx.BitmapButton(self.bitmap1, -1, pic2, pos = (300, 420),style=0,size=(50,50))self.Bind(wx.EVT_BUTTON, self.On2Click, self.button2)self.button2.SetDefault()#绘图按钮3,默认风格3Dself.button3 = wx.BitmapButton(self.bitmap1, -1, pic3, pos = (230, 480),style=0,size=(50,50))self.Bind(wx.EVT_BUTTON, self.On3Click, self.button3)self.button3.SetDefault()#绘图按钮4,默认风格3Dself.button4 = wx.BitmapButton(self.bitmap1, -1, pic4, pos = (300, 480),style=0,size=(50,50))self.Bind(wx.EVT_BUTTON, self.On4Click, self.button4)self.button4.SetDefault()def On1Click(self, event):print("人机交互")speaker.Speak("您已选择人机交互模式 ")chatwithrobot()event.Skip()def On2Click(self, event):print("音乐播放")speaker.Speak("您已选择音乐播放模式 ")music()event.Skip()def On3Click(self, event):print("天气播报")speaker.Speak("您已选择天气播报模式 ")weather()event.Skip()def On4Click(self, event):print("新闻播报")speaker.Speak("您已选择新闻播报模式 ")news()event.Skip()app = wx.App(False)
frame1 = wx.Frame(None, -1, title='Robot', size=(600, 640))
# create the class instance
panel1 = Panel1(frame1, -1)
frame1.Show(True)
app.MainLoop()

代码及图片地址:
链接:https://pan.baidu.com/s/1pIjEhUMss9cWIAtEmTSqhg
提取码:heao


http://www.ppmy.cn/news/460708.html

相关文章

分体式水晶头_超6类双屏蔽网线水晶头制作简易教程

本帖最后由 first1st 于 2017-9-10 08:47 编辑 最近看好多朋友都在纠结家装用什么网线。 个人刚好前段时间也装修了房子,用的超六类双屏蔽网线,就随便说一下,顺便做个教程。如果有什么做错的地方,请各位大神轻喷23333 简单说一下吧,用这个线,也是受到论坛的影响,弄好了以…

计算机无法联网 如何解决,电脑无法连接网络或不能正常上网的解决方法

电脑无法连接网络或不能正常上网的解决方法 随着科技的发展,电脑在人们生活中发挥着越来越重要的作用。当我们在使用电脑时,经常会出现网络正常却无法连接上网的情况。接下来就由小编来告诉大家如何解决。 具体如下: 1.当我们电脑的网线、路由器没有问题,且向相关部门电话查…

我用一根网线,控制了整栋楼的网络

本文转载自程序员不高兴 刚上大学没多久&#xff0c;就遇到件头疼事。 富二代们刚来就带着笔记本电脑&#xff0c;这让咱们只能玩手机的屌丝辈们羡慕嫉妒恨。要命的事来了&#xff0c;晚上断电不断网&#xff0c;于是熄灯后笔记本仍然可以玩。 不巧的是&#xff0c;我们寝室也…

网线接法大全(RJ45型网线插头)

一般情况下我们都是用的网线标准接法是568B 白橙- 橙 -白绿 -蓝- 白蓝- 绿 -白棕- 棕 其实真正通信的只有四芯,1- 2 -3 -6 只要你把 白橙 - 橙 - 白绿 -绿 四组芯线插入相应的线槽中,即可通信 其实我们用的网线标准接法是568B 白橙- 橙 -白绿 -蓝- 白蓝- 绿 -白棕- 棕 其实真…

在卧室墙壁的网线口串联连接一个无线路由器

路由器通电后&#xff0c;恢复默认设置&#xff0c; 取一网线&#xff0c;一端连接路由器WAN口&#xff0c;另一端连接笔记本&#xff08;或者笔记本直接连接该无线网络&#xff09; 笔记本打开浏览器&#xff0c;登陆路由器后面的ip地址&#xff0c;并输入账号密码 点击“网…

在计算机中连接有线网络的接口是,网线在书房 现在要把电脑搬到卧室 卧室也有一个网线借口 请问直接连接那个接口可以上网吗...

室内两个网线接口,一个在客厅,一个在卧室现在是客厅那个连出来的可以用,问怎么才能让卧室那个同时起作 装个无线路由器!这样一个有线的,一个无线的!在家笔记本也可以上网了!###加一个路由器 2021-05-30 光纤进户主线,主卧室留一个网线头,小卧室留一个网线头,电视想上网,的需要一…

linux查看哪个网卡插着网线,(笔记)Linux下检测网卡与网线连接状态

Linux下检测网卡与网线连接状态,使用ioctl向socket发送SIOCETHTOOL命令字。 #include #include #include #include #include #include #include #include #include #include #include int get_netlink_status(const char *if_name); int main() {if(getuid() != 0)…

【c语言】-- 操作符汇总

&#x1f4d5;博主介绍&#xff1a;目前大一正在学习c语言&#xff0c;数据结构&#xff0c;计算机网络。 c语言学习&#xff0c;是为了更好的学习其他的编程语言&#xff0c;C语言是母体语言&#xff0c;是人机交互接近底层的桥梁。 本章来学习数组。 让我们开启c语言学习之旅…