Python实战之听书小子

前段时间在公众号《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/。

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

1、喝酒不开车

因此从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实战)