终于,还是用❤️Python向喜马拉雅❤️动手了
文章目录
- 终于,还是用❤️Python向喜马拉雅❤️动手了
- 一、需求介绍
- 二、网页分析
- 三、具体实现
- 1、获取得到频道的标题、icon、poster
- 2、获取得到具体音频的信息
- 四、完整的代码的展示:
- 五、运行效果展示
一、需求介绍
我们知道Python十分适合进行爬虫的操作的,现在,我们希望可以借助Python爬取喜马拉雅这个说书平台的一些信息。
首先,我们希望可以获取得到一个频道的信息,然后,获取一个频道里面的具体的说书的内容,也就是具体的音频的内容了啦。
整体的内容是:
频道->音频(一个频道会有多个音频的)
我们需要提取的内容是一个频道的icon、poster、标题、频道下面的音频链接以及音频的封面和标题。
二、网页分析
喜马拉雅平台的url是:
https://www.ximalaya.com/
我们点击那个频道:
进入以后,我们首先随便点击一个,比如:儿童频道,然后,点击某一个具体的频道下面的哪一行灰色的字,就可以进入到具体的某一个频道了:
比如,我们进入蜜桃姐姐的频道:
现在我们想要获取得到蜜桃姐姐这个频道下面的一些信息以及具体的音频信息。(其他的频道其实是类似的,因为整个网站的网页的设计其实是相通的,只不过是具体的内容不同而已了啦)。
三、具体实现
首先打开网页检查工具,方便与我们进行网页的分析:
1、获取得到频道的标题、icon、poster
这三个内容获取起来比较容易一些,而且比较好操作,因此我们首先解决这三个数据的获取:
首先导入模块,
import requests
import re
import json
# 导入相关的模块
然后,我们需要确定url,
这里说一句,频道主页的url如下:
https://www.ximalaya.com/zhubo/18522984/ 但是实际上,为了可以获取得到所有的音频,我们需要在这个url后面加一个album
https://www.ximalaya.com/zhubo/18522984/album/ (整个网站都是这样的哦,这个你也是可以自己进行探索,其实也就是如果他没有展示完整的话,你点一下全部就会进入到所有音频的页面,当然,这个频道比较少,一页就展示完毕了,但是为了普适性,我们还是需要加上url的哦)
我们定义一个函数来实现功能,这里传递的参数的url是主页的url,但是我们会在内部自动加一个album
def pares_xi_ma_la_ya(initial_url):
"""
这个函数是实现了解析喜马拉雅这个听书的网站的channels,
使用了多次访问的方式:
1、访问频道的主页;
2、访问某一个专栏;
3、访问专栏下面的一个具体的单独的连载内容之一的链接得到具体的真实音频的地址。
:param initial_url: 初始的 url,也就是待解析的 url ,这个其实就是频道的主页了啦
:return: 有 6 个变量需要返回,方便于后续写到数据库里面的操作:
video_img,
video_link,
video_title,
icon,
poster,
title
"""
url = initial_url + 'album/'
# 用户只会输入一个频道的信息,我们获取album需要自己加上一个album
# 其实是相当于我们获取得到了所有的音频信息,(全部)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'
}
# 设置请求头
link = url
# 这个是频道的url,这个是主频道的url也就是那个link
res = requests.get(url=url, headers=headers).content.decode()
# 获取得到频道主页返回过来的内容
# print(res)
通过这段代码可以向浏览器发送请求,得到请求以后,我们进行网页界面的分析
比如,我们通过下面的那个标签,课看出来我们的poster的具体链接是什么:
类似的方法,我们还可以找到标题以及icon的位置,当然,我们使用程序进行操作的话是需要使用正则表达式进行匹配的:
= re.findall(r"<title>主播:(.*?)</title>", res)[0].split("_")[0]
print(title)
# 读取得到频道的标题
icon = "https:" + re.findall(r'<img class="img iH_" src="(.*?)" alt=".*?">', res)[0]
print(icon)
# 读取得到频道的icon
poster = "https:" + re.findall(r'<div class="anchor-home-header-bg-box iH_" style="background-image:url\((.*?)\)"><div class="bottom-mask iH_"></div></div>', res)[0]
print(poster)
# 读取得到频道的poster
上述代码实现了以上所说的三个内容的解析。
2、获取得到具体音频的信息
这个网站是动态的网站,所以为了获取得到信息,我们必须进行多次的访问,首先,我们需要得到音频的基础信息,也就是标题、封面、音频存放的地址,然后,在通过音频存放的地址获取得到具体的真实的音频的存放信息以及音频本身的链接:
刚开始的那个data是获取得到每一个音频的基础信息的列表,然后再分割的时候由于分割的模式有一点点的缺陷,所以使用了一个循环将数据调整了一下,使得方便与后面的操作。
在得到基础的信息以后,我们又一次利用获取得到的基础信息构建新的url进行访问浏览器,得到了真实的音频的存放的地址信息。
然后,利用这个音频的存放的地址信息获取得到真实的音频链接。
具体的操作入下所示:
这里还是需要使用正则表达式进行匹配了啦。
具体代码如下所示:
= re.findall(r'"albumInfo":\{"albumList":\[(.*?)\],"totalCount":(.*?),', res)[0][0].split(",{")
# 找的具体的video的数据,然后把字符串分割开来了啦
for m in range(len(data)):
# 分割开来的字符串有一点问题,因此需要进行一定的设置了啦
# 分割开来的时候主要是把前面的括号给去掉了,所以这里需要把前面的那个括号给加回来哦
if m == 0:
# 第一个没有发生变化,所以说,这里是不需要进行变化的
continue
else:
# 其他的位置之前是给去掉了括号,这里给他加回来了
data[m] = "{" + data[m]
# data 是一个列表
# print(data)
video_title = []
# list
video_img = []
# list
video_link = []
# list
for j in data:
# 遍历data这个列表
j = json.loads(j)
# 处理JSON数据
video_title.append(j["title"])
# video 的标题(title)
video_img.append("https://" + j["coverPath"])
# 获取得到 video 的封面
album_url = f'https://www.ximalaya.com/revision/play/v1/show?id={j["id"]}&num=1&sort=0&size=30&ptype=0'
# 根据 video 的 id 访问 video 播放的界面
new_album_res = json.loads(requests.get(url=album_url, headers=headers).content.decode())
# video 播放的界面返回的数据
new_new_url_id = new_album_res["data"]["tracksAudioPlay"][0]["trackId"]
# 根据 video 的播放的界面返回来的数据中的 trackId 访问具体的某一个音频的位置的存放位置,
# 也就是说,根据播放界面返回的数据找到具体的音频存放位置的url
new_new_url = f'https://www.ximalaya.com/revision/play/v1/audio?id={new_new_url_id}&ptype=1'
"""
这是一个存放音频的位置的url
https://www.ximalaya.com/revision/play/v1/audio?id=359504050&ptype=1
"""
real_video_player_url = json.loads(requests.get(url=new_new_url, headers=headers).content.decode())["data"]["src"]
# 访问音频的具体的存放的位置可以得到音频最真实的url
# 也就是说,通过访问音频存放的位置的url,我们可以读取得到音频的真实地址
video_link.append(real_video_player_url)
# 添加音频的真实的地址
print(video_title)
print(video_img)
print(video_link)
# 查看一些信息,进行打印出来了啦。
以上就获取得到了我们需要的音频地一些信息。
我们所说的具体的音频的链接是这个东西:
综上所述,我们就是实现了频道的信息的解析以及具体的每一个音频的信息的解析与获取了啦。
四、完整的代码的展示:
整个代码是封装在一个函数里面的,我们只需要进行调用就可以了了啊:
"""
这个是进行解析喜马拉雅的模块了啦,
实现的功能是解析某一个给定的频道,获取得到频道的标题、icon、poster,
以及,频道内部的音频的链接(真实的音频的存放的位置)、音频的标题、音频的封面。
by hyx.
"""
import requests
import re
import json
# 导入相关的模块
# this is just an example of the channel
initial_url_of_example = 'https://www.ximalaya.com/zhubo/2390668/'
def pares_xi_ma_la_ya(initial_url):
"""
这个函数是实现了解析喜马拉雅这个听书的网站的channels,
使用了多次访问的方式:
1、访问频道的主页;
2、访问某一个专栏;
3、访问专栏下面的一个具体的单独的连载内容之一的链接得到具体的真实音频的地址。
:param initial_url: 初始的 url,也就是待解析的 url ,这个其实就是频道的主页了啦
:return: 有 6 个变量需要返回,方便于后续写到数据库里面的操作:
video_img,
video_link,
video_title,
icon,
poster,
title
"""
url = initial_url + 'album/'
# 用户只会输入一个频道的信息,我们获取album需要自己加上一个album
# 其实是相当于我们获取得到了所有的音频信息,(全部)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.84'
}
# 设置请求头
link = url
# 这个是频道的url,这个是主频道的url也就是那个link
res = requests.get(url=url, headers=headers).content.decode()
# 获取得到频道主页返回过来的内容
# print(res)
title = re.findall(r"<title>主播:(.*?)</title>", res)[0].split("_")[0]
print(title)
# 读取得到频道的标题
icon = "https:" + re.findall(r'<img class="img iH_" src="(.*?)" alt=".*?">', res)[0]
print(icon)
# 读取得到频道的icon
poster = "https:" + re.findall(r'<div class="anchor-home-header-bg-box iH_" style="background-image:url\((.*?)\)"><div class="bottom-mask iH_"></div></div>', res)[0]
print(poster)
# 读取得到频道的poster
data = re.findall(r'"albumInfo":\{"albumList":\[(.*?)\],"totalCount":(.*?),', res)[0][0].split(",{")
# 找的具体的video的数据,然后把字符串分割开来了啦
for m in range(len(data)):
# 分割开来的字符串有一点问题,因此需要进行一定的设置了啦
# 分割开来的时候主要是把前面的括号给去掉了,所以这里需要把前面的那个括号给加回来哦
if m == 0:
# 第一个没有发生变化,所以说,这里是不需要进行变化的
continue
else:
# 其他的位置之前是给去掉了括号,这里给他加回来了
data[m] = "{" + data[m]
# data 是一个列表
# print(data)
video_title = []
# list
video_img = []
# list
video_link = []
# list
for j in data:
# 遍历data这个列表
j = json.loads(j)
# 处理JSON数据
video_title.append(j["title"])
# video 的标题(title)
video_img.append("https://" + j["coverPath"])
# 获取得到 video 的封面
album_url = f'https://www.ximalaya.com/revision/play/v1/show?id={j["id"]}&num=1&sort=0&size=30&ptype=0'
# 根据 video 的 id 访问 video 播放的界面
new_album_res = json.loads(requests.get(url=album_url, headers=headers).content.decode())
# video 播放的界面返回的数据
new_new_url_id = new_album_res["data"]["tracksAudioPlay"][0]["trackId"]
# 根据 video 的播放的界面返回来的数据中的 trackId 访问具体的某一个音频的位置的存放位置,
# 也就是说,根据播放界面返回的数据找到具体的音频存放位置的url
new_new_url = f'https://www.ximalaya.com/revision/play/v1/audio?id={new_new_url_id}&ptype=1'
"""
这是一个存放音频的位置的url
https://www.ximalaya.com/revision/play/v1/audio?id=359504050&ptype=1
"""
real_video_player_url = json.loads(requests.get(url=new_new_url, headers=headers).content.decode())["data"]["src"]
# 访问音频的具体的存放的位置可以得到音频最真实的url
# 也就是说,通过访问音频存放的位置的url,我们可以读取得到音频的真实地址
video_link.append(real_video_player_url)
# 添加音频的真实的地址
print(video_title)
print(video_img)
print(video_link)
# 查看一些信息,进行打印出来了啦。
"""
这是我们需要进行提供的接口给数据库里面进行写入的:
list_of_video_image,
list_of_video_link,
list_of_video_title,
channel_icon,
channel_poster,
channel_title
=
parse_the_url.parsing.parsing_the_url(un_parsed_url)
"""
return video_img, video_link, video_title, icon, poster, title
# ok .
最后,我们是将那些需要获取的信息进行了打包然后返回去了啦,就是那个return:
return video_img, video_link, video_title, icon, poster, title
五、运行效果展示
我们运行代码,可以获取得到信息:
E:\Users\1\anaconda3\python.exe C:/Users/1/Desktop/ximalaya/main.py
蜜桃姐姐FM的专辑
https://imagev2.xmcdn.com/group36/M03/7F/5D/wKgJUlo_K87zjY5NAADpk_TCTWg086.jpg!strip=1&quality=7&magick=jpg&op_type=5&upload_type=cover&name=web_large&device_type=ios
https://imagev2.xmcdn.com/group12/M07/38/3C/wKgDW1WYuteCKwOEAAIKX6d5h9g681.jpg!strip=1&quality=7&magick=jpg&op_type=5&upload_type=cover&name=large_pop&device_type=ios
['蜜桃姐姐讲故事', '蜜桃姐姐亲子秀', '圆梦中国·春苗行动', '蜜桃姐姐睡前故事', '做最棒的自己', '蜜桃姐姐的直播', '蜜桃姐姐说百科', '德国亲子成长小百科', '蜜桃姐姐:育儿常识', '蜜桃姐姐说成语']
['https:imagev2.xmcdn.com/group81/M08/B5/AD/wKgPEl7PX9HCxCRbAALZdthNWIg167.png', 'https:imagev2.xmcdn.com/group74/M06/D3/B2/wKgO3F6G0QeQ4rgcAClbkQYkgDA12.jpeg', 'https:imagev2.xmcdn.com/group63/M00/84/38/wKgMclz-JrPxKzJoAAMGquiTQQI98.jpeg', 'https:imagev2.xmcdn.com/group54/M02/98/E2/wKgLclw0Ht_RjdnIAALL7RBnKvs694.jpg', 'https:imagev2.xmcdn.com/group7/M04/0B/05/wKgDX1bMHIqDtnAyAAEn0yhCMvg081.jpg', 'https:imagev2.xmcdn.com/group42/M05/7F/83/wKgJ9FqyYrXzZ5CxAAEphLlEu0o579.jpg', 'https:imagev2.xmcdn.com/group11/M05/86/F9/wKgDbVYKnNaBtobRAAE29gbmJtY138.jpg', 'https:imagev2.xmcdn.com/group10/M00/73/A6/wKgDZ1X9afnxFpDjAAH9vHmdZGg128.jpg', 'https:imagev2.xmcdn.com/group9/M09/C5/81/wKgDYlZloFPiwI0RAAG2kyld6Z4371.jpg', 'https:imagev2.xmcdn.com/group11/M05/86/F8/wKgDbVYKnMORT-p2AAEiK97RaBA079.jpg']
['https://aod.cos.tx.xmcdn.com/group7/M07/52/BD/wKgDWlW2Da3iecvLACL3TejGko4253.m4a', 'https://aod.cos.tx.xmcdn.com/group74/M08/D4/95/wKgO3F6G3srBxmSBAA6sOb08ssY571.m4a', 'https://aod.cos.tx.xmcdn.com/group61/M0B/3C/A2/wKgMZl0HU3bAWUONAC2qO9gZ7l4883.m4a', 'https://aod.cos.tx.xmcdn.com/group53/M00/F4/0D/wKgLfFwglZLDfnmWADNIjvAStsw775.m4a', 'https://aod.cos.tx.xmcdn.com/group14/M07/0A/A4/wKgDZFbK-tnj1tdTADM7-GBQZbE452.m4a', 'https://aod.cos.tx.xmcdn.com/group42/M04/7F/9B/wKgJ81qyYg_yEOdbAp7kaAErdO8220.m4a', 'https://aod.cos.tx.xmcdn.com/group16/M01/2F/73/wKgDalWM_62i2zbxAA9qQ5fR5eU071.m4a', 'https://aod.cos.tx.xmcdn.com/group10/M06/63/51/wKgDZ1XbBZjiKMf5ADH-l-z89ns618.m4a', 'https://aod.cos.tx.xmcdn.com/group9/M01/94/1D/wKgDYlY6KJ7zjWBGACefiXJDZfI753.m4a', 'https://aod.cos.tx.xmcdn.com/group11/M03/43/54/wKgDbVWk1YDhBbS7AA3WfUKy2Y0718.m4a']
Process finished with exit code 0
我们从中是可以得到一些信息的,例如标题:
我们还可以得到icon以及poster
后面是还有音频的封面以及具体的音频的地址的,过于多,我们就不展示了:
综上所述,这就是一个动态的爬虫的信息的获取案例,希望对大家有一些帮助了啦,最后感谢大家的阅读与支持,如果喜欢的话就点一个赞嘛。