前段时间闲得无聊,使用python抓取了自己想看的小说,抓取方法:一个资深小说迷打开小说的正确姿势

最近发现连续长时间盯着屏幕,眼睛实在是有点遭不住。对于我这种又想保护视力,又不想放下小说的人来说,简直就是遇到了像 “ 鱼与熊掌不可兼得” 一般的世纪难题。

正当我思考如何两害取其轻的时候,有人私信我帮忙做一个文字转语音的接口,我突然灵机一动,这简直就是送上门来的满分答案啊

当然,对于我这种社畜来说,是万万不可能自己实现文字转语音功能的,我没有那个精力,更没有那个 money

不过,咱不会煮饭,咱还不会点外卖么?O(∩_∩)O哈哈~

打开快被我点裂开了的 google chrome 搜了搜,果然很多公司都提供现成的免费接口,比如百度、讯飞…最后我选择了百度AI接口(这种东西啊,就和点外卖是一样的,同样都是芋儿鸡,店家不一样,做出来的味道就有好有坏。当你都没吃过时,牌子大一点的店或许是个不坏的选择)

言归正传,首先你得去百度控制台登录一下,没有百度账号的需要注册:
https://ai.baidu.com/tech/speech

然后需要创建一个应用,创建好了之后,就能拿到我们想要的三个东西

然后,python需要安装两个库(百度接口库和语音播放库),如果不需要python播放音频的话,只需要安装第一个库就行:
pip install baidu-aip
pip install playsound
根据百度提供的接口文档https://ai.baidu.com/ai-doc/SPEECH/Gk4nlz8tc,我们可以很容易的将一段文本翻译成音频文件,如:
from aip import AipSpeech # 导入api接口
from playsound import playsound # 音频模块#对应填入百度控制台获取的三个参数
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)data = '你是最棒的,hello world'
result = client.synthesis(data, 'zh', 1, {'per': 4,'spd': 3, # 速度'vol': 7 # 音量
})
if not isinstance(result, dict):with open('hello.mp3', 'wb') as f:f.write(result)# 播放
playsound("hello.mp3")
上面这段代码,你只需要对应的填入百度后台获取的三个参数,然后运行文件,就会在你的代码文件同级目录下生成一个音频文件hello.mp3,并且会有美女夸你

有美女夸固然是好,可是我们最初的梦想是听小说啊。

别着急,你只需要将代码中的 data 内容换成咱们使用爬虫爬下来的小说内容,如:
#读取文本文件内容with open(file_name, 'r', encoding='utf-8') as f:data = f.read()
此时要注意,百度API每一次翻译的文本长度必须小于1024字节,小说每一章的内容往往大于1024字节,怎么办呢?
咱们可以将文本分割,然后多次请求就行了,写一个分割方法,像这样:
#按指定字节数分割字符串
def byte_split(seq):list = []while seq:if len(seq) >= 1024:list.append(seq[:1024])seq = seq[1024:]else:list.append(seq)seq = []return list
简单封装一下,第一版就出炉啦:
from aip import AipSpeech # 导入api接口
from playsound import playsound # 音频模块
import sys#百度账号信息配置
#对应填入百度控制台获取的三个参数
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)#按指定字节数分割字符串
def byte_split(seq):list = []while seq:if len(seq) >= 1024:list.append(seq[:1024])seq = seq[1024:]else:list.append(seq)seq = []return list'''@desc 写入音频@param data_arr list 文件数组@param vedio_name string 音频文件名@return 音频文件名
'''
def vedio_write(data_arr, vedio_name):name = vedio_name + '.mp3'for i in data_arr:#请求百度接口,获取语音二进制result = client.synthesis(i, 'zh', 1, {'per': 4,'spd': 3, # 速度'vol': 7 # 音量})#判断是否翻译成功-成功则写入,失败则打印错误信息if not isinstance(result, dict):with open(name, 'ab') as f:f.write(result)else:print(result)return name #主函数
if __name__ == "__main__":#文本文件file_name = r'../novel/quanzhifashi/第1章 世界大变.txt'#音频文件名vedio_name = file_name.split('/')[-1].split('.')[0]#读取文本文件内容with open(file_name, 'r', encoding='utf-8') as f:data = f.read()#按字符串拆分成数组data_arr = byte_split(data) #写入音频,返回音频文件名vedio = vedio_write(data_arr, vedio_name) # 播放playsound(vedio)
点击运行,在我的保存目录找到了自己想要的结果

但是并没有给我播放视频,而且反手扔给我一个Error

查看报错信息发现,由于我的音频文件是中文名,所以播放失败了,将中文换掉就可以正常播放。
但是总有像我一样杠中带倔的人,喜欢将音频文件命名为中文,怎么办呢?当然是打开我那要裂开了的google chrome 啊。巡视了一圈,最后发现pygame库可以解决这个问题。好嘛,安装pygame库:
pip install pygame
封装个方法,使用pygame播放音频:
# 播放音频
# 貌似只能播放单声道音乐,可能是pygame模块限制
def playMusic(filename, loops=0, start=0.0, value=0.5):""":param filename: 文件名:param loops: 循环次数:param start: 从多少秒开始播放:param value: 设置播放的音量,音量value的范围为0.0到1.0:return:"""flag = False # 是否播放过pygame.mixer.init() # 音乐模块初始化while 1:if flag == 0:pygame.mixer.music.load(filename)# pygame.mixer.music.play(loops=0, start=0.0) loops和start分别代表重复的次数和开始播放的位置。pygame.mixer.music.play(loops=loops, start=start)pygame.mixer.music.set_volume(value) # 来设置播放的音量,音量value的范围为0.0到1.0。if pygame.mixer.music.get_busy() == True:flag = Trueelse:if flag:pygame.mixer.music.stop() # 停止播放break
再将之前的代码整合一下子,最终版本就出炉了:
from aip import AipSpeech # 导入api接口
#from playsound import playsound # 音频模块
import sys
import pygame#百度账号信息配置
#对应填入百度控制台获取的三个参数
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)#按指定字节数分割字符串
def byte_split(seq):list = []while seq:if len(seq) >= 1024:list.append(seq[:1024])seq = seq[1024:]else:list.append(seq)seq = []return list'''@desc 写入音频@param data_arr list 文件数组@param vedio_name string 音频文件名@return 音频文件名
'''
def vedio_write(data_arr, vedio_name):name = vedio_name + '.mp3'for i in data_arr:#请求百度接口,获取语音二进制result = client.synthesis(i, 'zh', 1, {'per': 4,'spd': 3, # 速度'vol': 7 # 音量})#判断是否翻译成功-成功则写入,失败则打印错误信息if not isinstance(result, dict):with open(name, 'ab') as f:f.write(result)else:print(result)return name # 播放音频
# 貌似只能播放单声道音乐,可能是pygame模块限制
def playMusic(filename, loops=0, start=0.0, value=0.5):""":param filename: 文件名:param loops: 循环次数:param start: 从多少秒开始播放:param value: 设置播放的音量,音量value的范围为0.0到1.0:return:"""flag = False # 是否播放过pygame.mixer.init() # 音乐模块初始化while 1:if flag == 0:pygame.mixer.music.load(filename)# pygame.mixer.music.play(loops=0, start=0.0) loops和start分别代表重复的次数和开始播放的位置。pygame.mixer.music.play(loops=loops, start=start)pygame.mixer.music.set_volume(value) # 来设置播放的音量,音量value的范围为0.0到1.0。if pygame.mixer.music.get_busy() == True:flag = Trueelse:if flag:pygame.mixer.music.stop() # 停止播放break#主函数
if __name__ == "__main__":#文本文件file_name = r'../novel/quanzhifashi/第1章 世界大变.txt'#音频文件名vedio_name = file_name.split('/')[-1].split('.')[0]#读取文本文件内容with open(file_name, 'r', encoding='utf-8') as f:data = f.read()#按字符串拆分成数组data_arr = byte_split(data) #写入音频,返回音频文件名vedio = vedio_write(data_arr, vedio_name) #音频播放playMusic(vedio)#playMusic('out.wav')# 播放#playsound(vedio)
谁说鱼与熊掌不可兼得?
The end !
一个人最好的生活状态,有自己的生活和情趣,努力完善自己。没人爱时专注自己,有人爱时,有能力拥抱彼此。



















