admin管理员组

文章数量:1516870

手把手教学生成听小说

手把手教学生成听小说

  • 题记
  • 爬取小说
  • 生成小说语音
  • 后记

题记

小说除了看之外 ,还可以听。比如喜马拉雅、蜻蜓等APP推出了有声小说,但是那些好听的小说,就要你交钱。
有声小说的确挺好听的,朗读有感情,因此,我们可以降低一些要求,不需要太多有感情的朗读,已经可以了解这个小说。
本篇文章主要介绍将文字版的小说(以《庆余年》为例),转变成语音版的小说。

Created with Raphaël 2.2.0开始爬取小说通过百度云语音技术转换成语音结束

爬取小说

  • 获取网页的html内容
# 获取每一个网页的内容def getOnePage(url):response = requests.get(url)try:if response.status_code == 200:return response.textelse:return Noneexcept Exception as e:print(e)return None
  • html内容解析
    • 将小说内容保存成txt
# 解析动作
def parseAction(text):soup = bs4.BeautifulSoup(text, 'html.parser')page_id, title, article_data = parseArticle(soup)saveTxt(page_id, title, article_data)next_link = parseNextLink(soup)if next_link:return URL_BASE + next_linkelse:return Nonepass
# 解析出文章内容
def parseArticle(soup):article_datas = soup.select('#content')if len(article_datas)>0:article_data, page_id = parseUselessTag(article_datas[0])# print(article_data)return page_id, soup.title.text, article_data# saveTxt(page_id, soup.title.text, article_data)return Nonepass
# 去除无用的信息
def parseUselessTag(article_data):ret = re.sub('<br/>', '\n', str(article_data))ret = re.sub('<div.*?>', '', ret)ret = re.sub('</div>', '', ret)ret = re.sub('<script>.*?>', '', ret)page_id = re.findall('(\w+)\.html', ret)[0]ret = re.sub('https://.*?\w.*\s+.+com', '', ret)return ret, page_id
- 获取下一章节的链接 
# 解析下一章节链接
def parseNextLink(soup):lis = soup.find_all('li')for li in lis:if '下一章' == li.a.text:link = li.a['href']try:ar_id = re.findall('/(\w*)/', link)[0]except Exception:ar_id = Nonetry:page_id_html = re.findall('/(\w*.html)', link)[0]except Exception:page_id_html = Noneprint(ar_id, ',', page_id_html)if ar_id == ARTICLE_ID:return page_id_htmlelse:return Nonereturn Nonepass

生成小说语音

  • 从txt文件中获取内容及标题
# 遍历所有文件
def get_one_file(path):for root, dirs, file_names in os.walk(path):file_names.sort()for file_name in file_names:# 多加一个因为停止后重新跑的开始IDfile_id = re.findall('(\d+)_', file_name)[0]if int(START_ID) < int(file_id):article_data = get_one_article(file_name)yield article_data, file_name# exit()
# 从文件中获取小说内容
def get_one_article(file_name):print(file_name)article_data = ''with open('./'+ARTICLE_PATH+'/'+file_name, 'r', encoding='utf-8') as f:article_data = f.read()return article_data
  • 将文本转换成语音并保存
# 生成语音合成对象
def getSpeechObj(AppID=APPID, APIKey=APIKEY, SecretKey=SECRETKEY):speecher = AipSpeech(AppID, APIKey, SecretKey)return speecher
# 生成语音文件,注意文本长度不能超过1024byte
def do_synthesis(speecher, text):# 这里做一个对text长度进行切片1024以内texts = text.split('\n')text_list = []text_temp = ''for text_i in texts:if len(text_temp) < 800:text_temp = ''.join([text_temp, text_i])else:text_list.append(text_temp)text_temp = ''text_list.append(text_temp)for i, text_slice in enumerate(text_list):voice_data = speecher.synthesis(text_slice, options={'per': 4, 'spd': 3})yield voice_data, i
# 将切片的文字片段,在语音形式下组合成一个文件
if __name__ == '__main__':speecher = getSpeechObj()for art, f_name in get_one_file(ARTICLE_PATH):with open('./'+SAVE_VOICE_PATH+'/'+f_name[:-3]+VOICE_TYPE, 'wb') as f:for voice, i in do_synthesis(speecher, art):if not isinstance(voice, dict):f.write(voice)else:print(voice)print('Error f_name: {}!'.format(f_name))

注意,这里使用的百度语音技术的申请可以参考我之前的文档(百度语音合成创建应用的操作指引)。

后记

有了这个自己写的小说语音生成器,就可以自己生成想要的小说去听,虽然小说听起来没有收费的好听,但基本功能是可以的。
合成的语音可以有多种语音效果,通过synthesis的option变量选项。
项目地址AlexDish/Novel2Voice

本文标签: 手把手教学生成听小说