基于人工智能的盲人阅读器

本文在原码基础上做出很多修改,很感谢博主提供项目开发基础,有读者如果想看原文请点击原文链接:https://blog.csdn.net/aqqwvfbukn/article/details/106349903.


引言

编写目的

为详细介绍人工智能盲人阅读器的研究过程,防止用户操作不当,请各位用户在使用之前仔细阅读该手册,本次软件开发主要面向盲人用户使用。

背景

随着互联网的发展,人工智能、云计算大数据等行业为社会发展趋势,科技充满在生活,希望每个人都能感受到科技发展带来的便捷,生活变得越来越智能化。而在我国,盲人占比较大,科技发展的同时如何要让他们受益?所以为满足盲人的阅读需求,这里开发一款智能盲人阅读器,该软件与其他阅读器的不同之处就是增加音乐播放、人机交互、新闻播放功能,让科学技术走进盲人的世界。

一、软件概述

(一)名称

【人工智能盲人阅读器】

(二)简介

人工智能盲人阅读器,主要针对盲人、老年人群体开发,增加盲人获取外界信息的途径。该软件共有四项主要功能:书籍阅读、音乐播放、人机交互以及新闻播报功能。书籍阅读功能需要提前将播放书籍下载到本地,通过音频转化模块实现将文本内容转化为对应 MP3 文件;音乐播放功能直接选择音乐播放模式说出需要听的音乐即可;人机交互功能已设定人机对话次数只有 10 次;新闻播放功能直接选择新闻播放模式即可播放前 10 条最新时政新闻。

二、运行环境

(一)系统版本

Windows10

(二)运行内存

4GB+

(三)Python版本

Python3.9

(四)接口

外部接口

鼠标
音响
麦克风

内部接口

百度API
图灵机器人API

三、整体设计

下面是该软件的整体设计流程图:

在这里插入图片描述

(一)音乐播放模式

流程图展示:

在这里插入图片描述

开发流程说明:

音乐播放功能的工作机制较复杂,因为给用户做出反馈时要同时播报内容种类多,以及网页有加密设置。需要通过动态调试来解密两个参数。然后找到评论、歌词、歌曲以及搜索歌曲列表分别对应的 url,生成函数分别获取他们。继续生成一个音乐函数,为了让用户输入语音,即向图灵机器人 API 和百度 API 发送请求时,调用录音函数通过语音识别技术将语音信息合成文本,再转化为字符,使得图灵机器人 API 接口可以识别后做出反馈,接着调用上一个类里的函数下载音乐并保存在当前目录下的 data 文件夹中,最终反馈内容通过python 中的 pygame 模块播放。

(二)人机交互模式

流程图展示:

在这里插入图片描述

开发流程说明:

人机交互功能的工作机制中会用到图灵机器人API和百度API,这两个接口都需要注册,百度API注册之后可以领取免费语音合成额度(一定要记得领取!!!否则无法识别语音),但是图灵机器人API需要付费,根据需求,如果个人测试只需要基础版即可,做项目功能需求大可以买标准版套餐。
单击人机交互按钮进入该模式输入语音,此时系统会向图灵机器人API发送请求,同时百度API会调用录音函数将输入语音信息进行语音合成文字,最后图灵机器人会使用内部机制给用户做出语音反馈。

(三)书籍阅读模式

流程图展示:

在这里插入图片描述

开发流程说明:

书籍阅读功能的工作机制是用户单击书籍阅读模块按钮,然后对机器说出要听的书名(本地文件夹存在的书),即输入语音,系统调用事先定义的录音函数,再将该段语音信息通过百度 API 接口中的语音识别技术转化为文本,后转化为字符类型拼接成 mp3 文件。
这里有一点需要注意,就是要提前将想听的书籍下载或利用爬虫技术存放到本地,因为还要将下载下的文本文件进行音频文件转化处理,音频转化处理通过百度 API 接口语音合成技术合成 mp3 文件,此时才能通过输入的语音信息匹配搜索对应本地文件,最后利用 python 中的 pygame 模块实现书籍播放。

(四)新闻播放模式

流程图展示:

在这里插入图片描述

开发流程说明:

新闻播放功能的工作机制比较简单,用户进入新闻播放模式之后,直接会播放每条新闻的时间、标题以及部分内容,播放的新闻来源于中国新闻网的最新时政新闻。主要利用爬虫技术和 python 中的 pyttsx3,其中爬虫技术爬取新闻时需要打开浏览器开发者模式的界面,对 html 文档中的多个标签通过 Xpath定位,提取所需标签,新闻的时间、标题、内容标签都是列表类型,利用zip()高阶函数遍历多个标签列表,将每条新闻对应的时间、标题及内容一一输出,最后调用 pyttsx3 播放。

注:以上 4 个模块运行后会产生 wav 格式的音频文件,以及音乐模块会产生 mp3 文件,都默认保存在 main 文件所在目录的 data 文件夹中。本文格式文件用 pyttsx3 播放,音频文件用 pygame 播放。

(五)GUI界面设计

流程图展示:

在这里插入图片描述

开发流程说明:

python 中做界面设计 wxpython 是一款简单易上手的工具包。该软件界面设计首先创建了一个标题为“小 T”,大小为 600600 框架,保持框架默认缩小、放大、关闭三项设置,框架上放一个面板,用于布局其他控件,指定当前面板为 gridsizer 类型布局管理器。因为有 4 个功能模块,需要利用类wx.BitmapButton 创建 4 个位图按钮,所以建立 22 网格的简单网格化器,将每个按钮绑定对应事件触发函数。按钮上显示一个图片,而非一个文本标签,所以利用 wx.Image()获取位图按钮上的图片。最后将封好的每个按钮(控件)通过 AddMany()函数放到二维网格面板中。

四、运行结果展示

在这里插入图片描述

(一)音乐播放模式

在这里插入图片描述

(二)人机互动模式

在这里插入图片描述
[ ]中的信息是系统将用户输入内容转化成文本后输出,进行人机交互之后用户得到的反馈内容全部为语音输出。

(三)书籍阅读模式

在这里插入图片描述

(四)新闻播放模式

在这里插入图片描述

五、核心技术支持

(一)语音技术

百度API

在Python中使用该接口时需要提前导入baidu-aip, 目前AI产品主要有两种方式使用:API与SDK。

官网地址: https://ai.baidu.com/ .

获取凭证

在官网创建应用完毕后,平台将会自动分配此应用的相关凭证,主要为AppID、API Key、Secret Key三个信息,是应用实际开发的主要凭证。创建完成后一定要去服务列表里的语音识别和语音合成处领取免费的基础音库API的5000次额度,否则无法使用接口。
在这里插入图片描述

语音识别

目前语音识别系统支持的语音时长上限为60s,请不要超过这个长度,否则会返回错误。当前系统语言支持中文普通话(能识别简单的常用英语)、英语、粤语、四川话识别。并且通过在请求时配置不同的pid参数,选择对应模型,详见 请求说明dev-pid参数表格:

在这里插入图片描述

可以在语音识别词库上传识别自定义词条,训练语言模型,提交的语料越多、越全,语音识别的效果提升也会越明显。

语音合成

百度API语音合成文本长度必须小于1024字节(512个字),如果本文长度较长,可以采用多次请求的方式,切忌文本长度超过限制,合成文件格式为mp3。

图灵机器人API

介绍

图灵机器人是中文语境下智能度最高的“机器人大脑”,是全球较为先进的机器人中文语言认知与计算平台,图灵机器人对中文语义理解准确率已达90%,可为智能化软硬件产品提供中文语义分析、自然语言对话、深度问答等人工智能技术服务。图灵机器人是加载在机器人身上的类似于Siri的一整套语音语义系统。图灵机器人API是在人工智能的核心能力的基础上,为广大开发者、合作伙伴和企业提供的一系列基于云计算和大数据平台的在线服务和开发接口。特别注意在调用图灵API的各个环节的编码方式必须为UTF-8
图灵机器人官网:http://www.tuling123.com.

获取密钥

进入图灵机器人官网首先需要创建一个自己的机器人,获得apikey密钥,保存。
在这里插入图片描述

功能

图灵机器人API接口可调用聊天对话、语料库、技能三大模块的语料。聊天对话是指平台免费提供的近10亿条公有对话语料,满足用户对话娱乐需求;语料库是指用户在平台上传的私有语料,仅供个人查看使用,帮助用户最便捷的搭建专业领域次的语料;技能服务是指平台打包的26种实用服务技能。涵盖生活、出行、购物等多个领域,一站式满足用户需求。
免费版中只支持文本数据类型,在专业版中,支持图片,图文、视频、音频等富媒体回复(仅限微信公众号)。本次项目购买的是标准版套餐,调用量为1000次/天,知识库存储量为1000条,支持20种技能,包括三大类:

智能工具:图片搜索、数字计算、语料库、中英互译
休闲娱乐:笑话大全、故事大全、成语接龙、新闻资讯、星座运势、脑经急转弯、歇后语、绕口令、顺口溜、聊天对话
生活服务:天气查询、菜谱大全、快递查询、列车查询、日期查询、附近酒店、汽油报价、股票查询、城市邮编

(二)爬虫

XPath的全称是XML Path Language,即XML路径语言,是一种在XML(HTML属于XML)文档中查找信息的语言,XML文档是由一系列节点构成的树。他有4点特性:

  1. XPath使用路径表达式在XML文档中进行导航
  2. XPath包含一个标准函数库
  3. XPath是XSLT中的主要元素
  4. XPath是一个W3C标准。

使用XPath可以很容易定位到网页中的节点,找到需求数据,路径通过/来表示深度

官网:https://www.runoob.com/xpath/xpath-tutorial.html.

六、使用说明

由于软件针对人群是盲人用户,所以界面设计按钮较大,方便盲人快速找到按键。界面有4个按钮,以从左到右、从上到下排列规则分别为音乐播放模式、人机交互模式、书籍阅读模式和新闻播放模式,具体操作过程是用户只需选择按钮按下进入对应模式。

1、按下书籍阅读按钮,软件会提示用户进入书籍阅读模式,然后开始录音,此时用户说出需要阅读的书籍(书籍是提前下载好的书籍),当软件结束说出录音结束,停顿一会就会播放书籍。
2、按下新闻播放模式按钮,软件会提示进入新闻播报模式,此时软件会直接播放中国新闻网最新10条时政新闻。
3、按下音乐播放模式,软件提示进入音乐播放模式,开始录音,用户说出自己要听的音乐,软件结束录音,然后播放音乐。
4、按下人机交互按钮,软件提示进入人机交互模式,此时用户可以与软件聊天,聊天内容可见上方人机交互区包含功能。

参考资料

[1] aqqwvfbukn.Python开发智能语音机器人——小O同学
.https://blog.csdn.net/aqqwvfbukn/article/details/106349903,2020-05-26.
[2] 欧冬雨.基于百度API和图灵机器人的智能语音.https://blog.csdn.net/Bsrking/article/details/104071443,2020-01-22
[3] 科皮子菊.wxPython的gridSizer布局.https://piqiandong.blog.csdn.net/article/details/80742012,2018-06-20.
[4] 有道行的科学家.Python实例讲解 – wxpython 基本的控件 (按钮).https://blog.csdn.net/ztsghjls/article/details/54426228, 2017-01-14.
[5] 鹿鸣悠悠.python的爬虫【1】抓取链接+标题.https://blog.csdn.net/weixin_41665637/article/details/90637175,2019-05-28.
[6] 徽学院.wxPython BitmapButton图片按钮的用法.http://www.weixueyuan.net/a/844.html
[7] 马海淹没的小强.wxpython入门(1).https://blog.csdn.net/qq_39395805/article/details/100190866, 2019-09-02
[8] song527730241.使用xpath提取极客学院python课程内容名称.https://blog.csdn.net/song527730241/article/details/54585155,2017-01-17.
[9] Oblning.python实现文字转语音播报.https://blog.csdn.net/qq_19394437/article/details/97567298,2019-07-27.
[10] So_weak_yx.python写一个录音小程序.https://blog.csdn.net/yexiaohhjk/article/details/73132562,2017-06-12.
[11] waxly-.关于pycharm 安装 pyaudio失败的问题.https://blog.csdn.net/qq_43280079/article/details/99683448,2019-08-16.
[12] ZqtCtios.基于百度语音识别/百度tts/图灵机器人的语音小助手.https://github.com/ZqtCtios/robot,2019-4-26.

附录

# 导入录音接口的包
import pyaudio
# 导入打开录音文件并设置音频参数的包
import wave
import win32com.client
from aip import AipSpeech
# 初始化语音:SpVoice类是支持语音合成(TTS)的核心类,通过SpVoice对象调用TTS引擎,实现朗读功能
speaker = win32com.client.Dispatch("SAPI.SpVoice")
def record(file_path):
    """pyaudio参数"""
    # 数据包或者数据片段
    CHUNK = 1024
    # pyaudio.paInt16表示我们使用量化位数 16位来进行录音
    FORMAT = pyaudio.paInt16
    # 声道,1为单声道,2为双声道
    CHANNELS = 1
    # 采样率,每秒钟16000次
    RATE = 16000
    # 录音时间
    RECORD_SECONDS = 5
    # 录音文件保存为WAVE_OUTPUT_FILENAME
    WAVE_OUTPUT_FILENAME = file_path
    pau = 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)
    # 识别录音文件通过语音识别函数返回语音内容的文本,https://ai.baidu.com/ai-doc/SPEECH/1k4o0bmc7
    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()


# 人机互动
# 导入文本转语音的包
import pyttsx3
# 初始化语音库
engine = pyttsx3.init()
# 向api发送请求
def get_response(msg):
  apiUrl = 'http://www.tuling123.com/openapi/api'
  data = {
    'key': '图灵机器人API',
    'info': msg,
    'userid': 'pth-robot',
  }
  try:
    r = requests.post(apiUrl, data=data).json()
    engine.say(r.get('text'))
    engine.runAndWait()
    print(r.get('text'))
  except:
    return
def say():
    global chat_message
    # 存放的文件名称的文件夹data
    file_path = "data/chat-audio.wav"
    # 百度需要的参数
    APP_ID = ''
    API_KEY = ''
    SECRET_KEY = ''
    # 先调用录音函数
    record(file_path)
    # 调用语音识别函数voice2text()将语音内容转成文字
    chat_message = voice2text(APP_ID, API_KEY, SECRET_KEY, file_path)
    print(chat_message)
# 设定人机交互次数函数(即人与图灵机器人的对话次数,注意这里初始值为0小于10,只能调用9次而不是10次)
def chatwithrobot():
    i=0
    while i < 10:
        say()
        get_response(chat_message)
        i = i+1


# 音乐播放
import base64
import random
from binascii import hexlify
# 特别注意Crypto模块的首字母要改成大写,这是一个加解密模块,在爬取音乐评论用到
from Crypto.Cipher import AES
import json
import urllib, requests
import pyttsx3
import pygame
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/'}
        # requests库的session会话对象可以跨请求保持某些参数,说白了,就是比如你使用session成功的登录了某个网站,
        # 则在再次使用该session对象请求该网站的其他网页都会默认使用该session之前使用的cookie等参数
        self.session = requests.Session()
        self.session.headers = self.headers
        self.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 data
    def 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_name
            SongId=song_id
            Songer=songer
            self.get_music_url(song_id)
            self.get_music_lyric(song_id)
            self.get_music_comment(song_id)
            break
    def 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) % 16
        data = 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_str
    def 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"
    # 百度需要的参数
    APP_ID = ''
    API_KEY = ''
    SECRET_KEY = ''
    # 先调用录音函数
    record(file_path)
    # 语音转成文字的内容
    song_message = voice2text(APP_ID, API_KEY, SECRET_KEY, file_path)
    print(song_message)
    input2=''.join(song_message)  #转换成字符串
    song_name=input2[2:]
    Msuic = GetMusic()
    Msuic.get_music_list_info(song_name)
    songid=str(SongId)
    # 设置了一个headers,在构建request时传入,在请求时,就加入了headers传送,服务器会识别headers中的referer是不是它自己,服务器若识别了是浏览器发来的请求,就会得到响应。
    url = 'https://music.163.com/song/media/outer/url?id='+songid
    headers = { 'User-agent':
                'Mozilla/5.0 (X11; Linux x86_64; rv:57.0)Gecko/20100101 Firefox/57.0',
                'Host':'music.163.com',
                'Referer':'https://music.163.com'}
    req = requests.get(url, headers=headers, allow_redirects=False) #拒绝默认的301/302重定向
    musicLink = req.headers['Location']    #从而可以通过html.headers[‘Location’]拿到重定向的URL。
    urllib.request.urlretrieve(musicLink,'data/'+SongName+".mp3")  #下载并重命名文件
    # 初始化engine
    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 book():
    file_path="zh/red/music.wav"
    # 百度需要的参数
    APP_ID = ''
    API_KEY = ''
    SECRET_KEY = ''
    # 先调用录音函数
    record(file_path)
    # 语音转成文字的内容
    book_message = voice2text(APP_ID, API_KEY, SECRET_KEY, file_path)
    print(book_message)
    # 转换成字符串
    input2 = ''.join(book_message)
    book_name = input2[0:]
    # 初始化engine
    engine = pyttsx3.init()
    engine.say('即将为您播放'+book_name)
    # 合成语音
    engine.runAndWait()
    # 初始化混响器
    pygame.mixer.init()
    # 导入音频文件
    filename = r'zh/red/' + book_name+'.mp3'
    # 加载音频
    pygame.mixer.music.load(filename)
    # 循环播放
    pygame.mixer.music.play()


#新闻播报
def news():
    from lxml import etree
    import requests
    import pyttsx3
    # 中国新闻网时政类新闻url获取
    url = "https://www.chinanews.com/china/"
    # 采用get方法获取响应
    html = requests.get(url)
    # 将url转化为utf-8编码格式,否则爬取结果会出现乱码格式
    html.encoding = 'utf-8'
    # 用lxml模块中的html的etree将响应内容转换为可分析的标签
    selector = etree.HTML(html.text)
    # 用xpath获取所有时间,标题,内容的标签
    lis_time = selector.xpath('//ul[@class="news_list_ul"]/li//div[@class="left"]/text()')
    lis_title = selector.xpath('//ul[@class="news_list_ul"]/li//div[@class="news_title"]/em/a/text()')
    lis_text = selector.xpath('///ul[@class="news_list_ul"]/li//div[@class="news_content"]//a[@class="gray5"]/text()')
    # 播放新闻
    engine = pyttsx3.init()
    engine.say('即将为您播放最新时政新闻')
    engine.runAndWait()
    # 在python中要同时遍历多个列表,比较简单的方法就是使用zip()高阶函数,
    # zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回这些元组
    for time, title, text in zip(lis_time, lis_title, lis_text):
        a = (time + title + text)
        print(a)
        # 播放爬取内容
        engine.say(a)
        engine.runAndWait()

# wxpython是一个用于Python编程语言的跨平台GUI工具包。
# 可简单轻松地创建具有强大,高功能的图形用户界面的程序。
# 它被实现为一组Python扩展模块,它们包含流行的wxWidgets跨平台库的GUI组件,该 库是用C++编写的。
import wx
# 自定义一个窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        # 创建一个标题为“小T”,大小为600*600的框架
        wx.Frame.__init__(self, None, -1,title="小T",size=(600,600))
        # 在框架中放一个面板,用于布局其他控件
        panel = wx.Panel(parent=self)
        # 按钮上显示一个图片,而非一个文本标签,获取按钮位图按钮上的图片
        pic1 = wx.Image("yinyue.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        pic2 = wx.Image("hudong.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        pic3 = wx.Image("shu.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        pic4 = wx.Image("xinwen.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()

        # 在wxPython 中,使用类wx.BitmapButton 来创建一个位图按钮
        # 创建位图按钮1
        btn1 = self.button1 = wx.BitmapButton(panel, -1, pic1)
        # 创建位图按钮2
        btn2 = self.button2 = wx.BitmapButton(panel, -1, pic2)
        # 创建位图按钮3
        btn3 = self.button3 = wx.BitmapButton(panel, -1, pic3)
        # 创建位图按钮4
        btn4 = self.button4 = wx.BitmapButton(panel, -1, pic4)

        # 创建一个2乘2网格的简单网格化器,其垂直和水平间隙为5像素grid,垂直缝隙,水平缝隙
        gridsizer=wx.GridSizer(cols=2, rows=2, vgap=5,hgap=5)
        # AddMany()添加控件列表中的每个项目
        gridsizer.AddMany([(btn1,0,wx.EXPAND),(btn2,0,wx.EXPAND),(btn3,0,wx.EXPAND),(btn4,0,wx.EXPAND)])
        # 将控件添加到布局管理器中
        # gridsizer.Add(btn,0,wx.EXPAND)

        # 绑定事件函数,就是指定的button被单击后调用onClick()成员函数
        # Bind()方法 由wx.EvtHandler类中的所有显示对象继承。这里的EVT_.BUTTON是活页夹,它将按钮点击事件关联到OnClick()方法
        # 位图按钮1绑定On1Click()函数
        self.Bind(wx.EVT_BUTTON, self.On1Click, self.button1)
        self.button1.SetDefault()

        # 位图按钮2绑定On2Click()函数
        self.Bind(wx.EVT_BUTTON, self.On2Click, self.button2)
        self.button2.SetDefault()

        # 位图按钮3绑定On3Click()函数
        self.Bind(wx.EVT_BUTTON, self.On3Click, self.button3)
        self.button3.SetDefault()

        # 位图按钮4绑定On4Click()函数
        self.Bind(wx.EVT_BUTTON, self.On4Click, self.button4)
        self.button4.SetDefault()

        # 指定当前面板为gridsizer类型布局管理器
        panel.SetSizer(gridsizer)


    # 创建位图按钮1的触发事件函数
    def On1Click(self, event):
        print("音乐播放")
        speaker.Speak("您已选择音乐播放模式 ")
        music()
        event.Skip()

    # 创建位图按钮2的触发事件函数
    def On2Click(self, event):
        print("人机交互")
        speaker.Speak("您已选择人机交互模式 ")
        chatwithrobot()
        event.Skip()

    # 创建位图按钮3的触发事件函数
    def On3Click(self, event):
        print("书籍阅读")
        speaker.Speak("您已选择书籍阅读模式 ")
        book()
        event.Skip()

    # 创建位图按钮4的触发事件函数
    def On4Click(self, event):
        print("新闻播报")
        speaker.Speak("您已选择新闻播报模式 ")
        news()
        event.Skip()


# 创建应用程序
if __name__ == '__main__':
   app =wx.App()
   frame = MyFrame()
   # 显示主窗口
   frame.Show()
   # 启动事件循环
   app.MainLoop()




遇到的问题以及需要注意的点

1、pyaudio

这是python里的一个包,我在装这个包的时候遇到很多问题,具体解决办法可以参考链接:https://blog.csdn.net/qq_43280079/article/details/99683448

2、各轮地址

python下载各轮的地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/

3、lxml

python3.5之后的lxml中不再有etree模块,可导入使用
import lxml.html
etree = lxml.html.etree

4、XPath

利用XPath来定位XML文档的标签,可以去菜鸟教程详细学习,这里推荐两篇博客可以快速学习XPath,链接:https://blog.csdn.net/weixin_41665637/article/details/90637175
https://blog.csdn.net/rongDang/article/details/79826932

5、[<Element span at 0x23290bb6ec8>]

[<Element span at 0x23290bb6ec8>]错误运行结果解决方案:https://blog.csdn.net/work_you_will_see/article/details/84637076

6、No system module pywintypes

Python3.9 解决 ImportError: No system module pywintypes (pywintypes39.dll) 的方法链接:https://blog.csdn.net/u014663232/article/details/106799735

7、文件夹命名

python中命名文件时不能出现中文字符,否则无法识别

8、百度API

这个去官网注册之后必须创建应用才可以得到三个主要凭证,图灵机器人API同理需要创建一个机器人才能得到主要凭证

9、界面设计

界面设计可以参考链接:http://codingdict.com/article/9457

10、网页开发者模式进入

打开对应网页–右击–检查–network–f5刷新

11、网络环境

运行该程序必须连接网络

12、开发环境

我用的是python3.9开发,如果大家用2.+开发需要注意2和3的区别,下面是区别链接:https://www.runoob.com/python/python-2x-3x.html

13、位图按钮

创建位图按钮参考链接:http://www.weixueyuan.net/a/844.html

本次项目开发主要学习资源来自CSDN、Github、简书、菜鸟教程、博客园等等,这几个网站上有各大佬发出的优秀博客,非常推荐喜欢编程的童鞋们去学习,本人也是初学者,没发过几次博客,如果有什么问题,请各位指点,欢迎评论!!!

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值