由于家里小朋友暑假需要打卡古诗,经常需要去查询并下载古诗的朗诵音频文件,于是并写了一个简单的脚本用来爬取诗文及音频文件。
本代码就简单的进行爬取,未做优化,像下载这些都可以用一个函数简化代码,没有处理了。
具体代码如下:
import requests
from lxml import etree
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}
name = input('请输入要搜索的古诗名字:')
# name = '泊船瓜洲'
# 百度汉语查询窗口
url = 'https://hanyu.baidu.com/s?wd=' # 汉语首页
search_url = url+ name
response = requests.get(search_url,headers=headers)
# 解析返回的html文件
search_web = etree.HTML(response.text)
search_result = search_web.xpath('//*[@id="data-container"]/div')
# 获取诗文内容
def get_content(resp):
data_resp = resp.xpath('//*[@id="poem-detail-header"]') # 诗的正文部分内容
for i in data_resp:
title = i.xpath('./h1/text()')[0]
print(title)
author = i.xpath('./div[1]/a//text()|./div[1]/span//text()')
# 作者 朝代 由4个总分结合而成
new_author = ''.join([a.strip() for a in author])
print(new_author)
gs_body = i.xpath('./div[3]//*[@id="body_p"]//text()') # [@id="body_p"] 定位到原文一行
gs_means = i.xpath('./div[3]//*[@id="means_p"]//text()') # [@id="body_p"] 定位到译文一行
# 去掉获取的文本中间空格及空字符
new_gs_body = ''.join([b.strip() for b in gs_body])
new_gs_means = ''.join([m.strip() for m in gs_means])
print('诗句:', new_gs_body) # ./div[3]/p[1]/span[1]/span[1] |./div[3]/p[1]/*/text()
print('译文:', new_gs_means)
# 根据搜索内容获取查询到的诗文内容
if len(search_result)>0:
content = [] # 定义查询到的诗文的内容
# 查询到多个结果
for i in search_result:
# 只有文字链接和译文两行的情况
if len(i.xpath('./node()')) <= 2:
tmp=i.xpath('./div[1]/a/@href')+i.xpath('./div[2]/text()') # 没有作者信息的第一行内容
# 有文字链接、作者朝代、诗文三行内容
else:
tmp = i.xpath('.//@href')+i.xpath('./div/span/text()')+i.xpath('./div[last()]/text()')
# 获取链接页面参数:'.//@href' 作者:'./div/span/text()' 第二行内容:'./div[last()]/text()'
# 去掉结果中的空格以及/n字符
content.append([t.strip() for t in tmp])
# print(content)
for n,c in enumerate(content):
print(n,c)
while True:
num = input('请选择需要下载的诗的序号:')
if num == 'exit':
break
elif num.isdigit() and int(num) <= len(content)-1:
# 下载音频文件
print(content[int(num)])
down_url = 'https://hanyu-poem-mp3.cdn.bcebos.com/'+content[int(num)][0][-32:]+'.mp3'
print('音频下载地址:',down_url)
with requests.get(down_url,headers=headers) as down:
with open('D:\\txt\\{}.mp3'.format(name+content[int(num)][0][-6:]),'wb') as f:
f.write(down.content)
print('音频文件下载完成')
down.close()
# 获取诗文内容信息
content_url = 'https://hanyu.baidu.com'+ content[int(num)][0]
print('诗正文页面:',content_url)
with requests.get(content_url, headers=headers) as cont_response:
# 解析返回的html文件
cont_web = etree.HTML(cont_response.text)
# 获取诗文内容信息
get_content(cont_web)
cont_response.close() # 关闭请求
else:
print(' 输入的数字大于序号或输入的非数字,请重新输入!')
# 查询到一个结果,页面会直接显示诗文的全部内容,从百度首页重新查询并获取音频文件
else:
get_content(search_web)
# 下载音频
baidu_url = 'https://www.baidu.com/s?wd=' + name
baidu_response = requests.get(baidu_url, headers=headers)
# print(response.cookies)
# 解析返回的html文件
baidu_web = etree.HTML(baidu_response.text)
baidu_result = baidu_web.xpath('//*[@id="1"]/div/div[1]/div[3]/div[1]/div')
audio = baidu_result[1].xpath('./div[1]/div[3]/span/audio/@src')
print('音频:', audio) # /div[1]/div[3]/span/audio
# 下载音频文件
with requests.get(audio[0], headers=headers) as down:
with open('D:\\txt\\{}.mp3'.format(name + audio[0][-6:]), 'wb') as f:
f.write(down.content)
print('音频文件下载完成')
down.close()
response.close() # 获取完数据后关闭请求
使用方法:
直接运行代码,输入需要查询的古诗名字,在搜索结果中选择需要下载的相应序号,下载即可。下载文件的保存目录为:D:\txt,如果没有这个目录需要先建一个(或者修改代码中保存文件的位置),否则会错!
对于只有一个搜索结果的,百度汉语上没有音频文件的信息,跳转到百度首页重新搜索,并获取音频文件,但是有时会获取不到信息,待后面完善。
另外对于有多个结果的也不一定能下载到音频文件,暂时未获取到是否有音频文件的标志,所以如果下载的文件只有1K大小,那就是无用的下载。
# 古诗正文链接:
# https://hanyu.baidu.com/shici/detail?pid=2a8ba337af744ba1bc7d88b4a95eab20&srcid=51369
#
# # 音频文件链接
# http://hanyu-poem-mp3.cdn.bcebos.com/e1ee08f74e67482b97a6077aef2018de.mp3