欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python实战之听书小子

程序员文章站 2022-04-18 20:51:45
...

前段时间在公众号《Python爱好者社区》看到这篇文章:

https://mp.weixin.qq.com/s?__biz=MzI5NDY1MjQzNA==&mid=2247489917&idx=5&sn=4e5aa7626d480368c3edaa543a474b2f&chksm=ec5ec600db294f16a7d490f6a24e8296acea2069903a8749faafd8c4212872d4a6c6b3392454&mpshare=1&scene=1&srcid=0428PUNAL4ubKu9LSuT9YVft&sharer_sharetime=1588077632124&sharer_shareid=ac3ae07c07d7eeaa77ecab49b86cc99e&key=b057c75bc90186ba1d681e6a3712efacfd6535366253fadb64c9750f9936979c2542da3451446b54c51a2cf4e6c1f0c093045a3dda0b93923a066ee13f55d37c804ac434662b53cdf4168ec1942e22aa&ascene=1&uin=MjU2NzUxMzExMQ%3D%3D&devicetype=Windows+10+x64&version=62090070&lang=zh_CN&exportkey=A6XkASyz8tDXvDktPa1WOgY%3D&pass_ticket=ffVVHy6oiS17%2BgZMUytcIopIS5vv%2FOPxyRRLXt21%2FS1spi6t%2BQw%2FjBmA4F3kbWKg

觉得挺有意思,就和小伙伴一起写了一下当作学习python的练习。


语音合成

科大讯飞提供的语音合成有限制次数,只能免费调用500次,而百度提供的语音合成不限次数,但QFS限额为5,即一秒钟最多调用5次。于是果断选择用百度语音合成API。

注册一个百度账户,登录到百度AI智能平台,创建一个应用。

记录AppID、API Key、Secret Key,在调用API的时候会用到。

具体调用代码参考:https://ai.baidu.com/ai-doc/SPEECH/Gk4nlz8tc

result  = client.synthesis('你好百度', 'zh', 1, {
    'vol': 5,
})

# 识别正确返回语音二进制 错误则返回dict 参照下面错误码
if not isinstance(result, dict):
    with open('auido.mp3', 'wb') as f:
        f.write(result)

'zh'应该是中文的意思;'vol'选项为选择语音类型(1为普通男声,2为普通女声,3为度逍遥,4为度丫丫)。

此外,还可以通过参数调节音量、语调、语速等。

获取小说内容

小说内容从笔趣阁获取,原因是免费且没有反爬。首先选择一本小说,找到其网址。

这里以《我真没想重生啊》为例,其网址是http://www.biquge.info/69_69102/

观察网站源代码,发现章节信息为:

<dd><a href="12893198.html" title="1、喝酒不开车">1、喝酒不开车</a></dd>

因此从dd标签中获取章节名、章节链接。

def getChapters(self):
	"""获取所有章节信息(章节名、章节url)
	input:
	output:"""
	r=requests.get(self.main_url)
	r.encoding='utf-8'
	soup = BeautifulSoup(r.text,'html.parser')
	
	#每个章节
	cpts=soup.findAll('dd')
	num=1
	for cpt in tqdm(cpts):
	    if str(num) not in cpt.text:
			continue
		#章节名
		self.chapters_name[num]=cpt.text
		
		#章节url
		url=cpt.find('a')
		self.chapters_url[num]=url.get('href').split('.')[0]
			
		num+=1

然后使用BeautifulSoup.find(attrs={"id":"content"})来获取具体章节内容。

def getContents(self,chapter):
	"""获取指定章节内容"""
	r=requests.get(self.main_url+self.chapters_url[chapter]+'.html')
	r.encoding='utf-8'
	soup=BeautifulSoup(r.text,'html.parser')
	content=soup.find(attrs={"id":"content"})
	soup_text = BeautifulSoup(str(content), 'lxml')
	text=soup_text.div.text.replace('\xa0','')
	self.chapters_contens[chapter]=text

播放语音

使用pygame库,做法与上述文章一致。

def play(self,chapter):
	"""播放指定章节内容"""
	#如果没有下载章节内容则先下载
	if chapter not in self.chapters_contens:
		self.getContents(chapter)

	#调用百度语音合成API,把文字转成语音
	result = self.client.synthesis(self.chapters_contens[chapter][:1024], 'zh', 1, {"per": 4})
	if isinstance(result, dict):
		print('合成失败')
		
	#播放语音
	pygame_mixer = pygame.mixer
	pygame_mixer.init(frequency=16000)
	byte_obj = BytesIO()
	byte_obj.write(result)
	byte_obj.seek(0, 0)
	pygame_mixer.music.load(byte_obj)
	pygame_mixer.music.play()
	while pygame_mixer.music.get_busy():
		time.sleep(0.1)
	pygame_mixer.stop()

最终代码

from bs4 import BeautifulSoup
import requests
from aip import AipSpeech
from tqdm import tqdm
import time
import pygame
from io import BytesIO

class listenWebNovel():
	def __init__(self):
		"""初始化"""
		self.main_url='http://www.biquge.info/69_69102/'
		self.chapters_name=dict()
		self.chapters_url=dict()
		self.chapters_contens=dict()
		self.APP_ID=''#需改为个人APP_ID
		self.API_KEY=''#需改为个人API_KEY
		self.SECRET_KEY=''#需改为个人SECRET_KEY
		self.client = AipSpeech(self.APP_ID,self.API_KEY,self.SECRET_KEY)
		self.getChapters()
		
	def getChapters(self):
		"""获取所有章节信息(章节名、章节url)
		input:
		output:"""
		r=requests.get(self.main_url)
		r.encoding='utf-8'
		soup = BeautifulSoup(r.text,'html.parser')
		
		#每个章节
		cpts=soup.findAll('dd')
		num=1
		for cpt in tqdm(cpts):
			if str(num) not in cpt.text:
				continue
			#章节名
			self.chapters_name[num]=cpt.text
			
			#章节url
			url=cpt.find('a')
			self.chapters_url[num]=url.get('href').split('.')[0]
			
			num+=1
			
	def getContents(self,chapter):
		"""获取指定章节内容"""
		r=requests.get(self.main_url+self.chapters_url[chapter]+'.html')
		r.encoding='utf-8'
		soup=BeautifulSoup(r.text,'html.parser')
		content=soup.find(attrs={"id":"content"})
		soup_text = BeautifulSoup(str(content), 'lxml')
		text=soup_text.div.text.replace('\xa0','')
		self.chapters_contens[chapter]=text
		
	def play(self,chapter):
		"""播放指定章节内容"""
		#如果没有下载章节内容则先下载
		if chapter not in self.chapters_contens:
			self.getContents(chapter)

		#调用百度语音合成API,把文字转成语音
		result = self.client.synthesis(self.chapters_contens[chapter][:1024], 'zh', 1, {"per": 4})
		if isinstance(result, dict):
			print('合成失败')
		
		#播放语音
		pygame_mixer = pygame.mixer
		pygame_mixer.init(frequency=16000)
		byte_obj = BytesIO()
		byte_obj.write(result)
		byte_obj.seek(0, 0)
		pygame_mixer.music.load(byte_obj)
		pygame_mixer.music.play()
		while pygame_mixer.music.get_busy():
			time.sleep(0.1)
		pygame_mixer.stop()

if __name__ == '__main__':
	#实例化
	lw=listenWebNovel()
	#播放第1章
	lw.play(1)

 

相关标签: Python实战