网页音频抓取(听有声小说的音频地址是什么?如何借鉴本文的思路 )
优采云 发布时间: 2022-02-07 08:02网页音频抓取(听有声小说的音频地址是什么?如何借鉴本文的思路
)
前言:
一个朋友最近沉迷于听有声小说,但是因为很多有声小说网站需要VIP才能听,所以他想让我帮他把小说下载下来,这样他就可以在手机上随时听了电话。我在网上搜了他听的这本小说,确实有很多大型听书网站需要VIP才能听,于是找了一个小网站帮他爬小说拿去向下。因为他听的小说是知名作者写的,为了保护作者的权益,本文的案例没有使用作者的小说进行爬取,而是使用了另一部小说进行爬取说明,大致爬取思路是一样的,大家可以借鉴这篇文章的思路。
本案网站:
一、分析网页
本案小说共有178章,对应178个音频数据。我们需要爬取小说的名字,每章的链接地址,然后分析每一个链接地址,找到真正的音频。数据地址。如图所示:
网页的链接可以通过查看开发者工具来分析,该网页是html数据网页,数据也在html网页的源码中。继续分析,随意点击一个章节链接,网页跳转到另一个窗口,然后自动播放。本章的小说,如图:
事实上,找到音频文件非常简单。只需找到网络下的媒体选项,就可以看到正在播放的音频数据,如图:
从图中可以看出,音频数据是m4a格式的音频数据,而这个URL是真正的音频地址,所以问题是,只有这个URL只能爬取一章的小说,我们的目的是爬取所有章节的小说,所以显然只知道小说的音频地址是没有用的。接下来,我们需要找出音频地址的来源。通过经验,我们可以搜索到音频地址后面的文件名。
通过搜索名称,我们找到了一个新的网页链接,如图:
可以清楚的看到和真实的音频地址是一样的,只是少了**.m4a**这几个字。我们大概断定这个网页就是收录真实音频数据的地址网页,但是这是一个新的,那么这个地址是从哪里来的呢?没关系,我们继续搜索这个地址试试。
可以看出,我们通过搜索找到了一个新的网页。里面有一个iframe标签,标签下面有一个src属性。里面的 URL 大概和我们之前搜索的网页的 URL 是一样的,但是这个 URL 并不完整。,只有URL的后半部分,前半部分不见了,我们只需要完成前半部分,通过这一系列的分析,大概确定这个URL就是收录上述URL的数据URL,最后我们只需要确定 URL 使用任何 URL 就足够了。确认后,URL为各章节的链接地址。即使完成了整个分析过程,小说的有声读物也基本可以爬取。
现在我们来谈谈爬行的想法。首先通过小说首页爬取每章的链接地址和小说名,然后通过爬下来的每章的链接找到链接地址中收录的另一个。一个收录真实音频数据的小说链接,通过这个链接找到真实的音频数据,最后保存数据。
在这种情况下使用的模块:
1import requests
2import parsel
3import re
4import os
5from urllib.request import urlretrieve
6from tqdm import tqdm
7
8
二、发送请求并获取响应数据
1 def parse_url(self, url, headers):
2 """
3 发送请求,获取响应数据的方法
4 :param url:
5 :param headers:
6 :return:
7 """
8 response = requests.get(url, headers=headers)
9 if response.status_code == 200:
10 return response.text
11 else:
12 print('请求失败')
13
14
三、提取小说各章链接地址
1 def get_chapter_url(self, html_str):
2 """
3 提取小说章节的url的方法
4 :param html_str:
5 :return:
6 """
7 html = parsel.Selector(html_str)
8 # 提取小说章节地址列表
9 chapter_urls = html.css('#playlist>ul>li>a::attr(href)').extract()
10 chapter_urls = [self.SHU_TEMP_URL.format(i) for i in chapter_urls]
11 # 提取小说名字
12 audio_shu_name = html.css('.book-title::text').extract_first().strip()
13 return chapter_urls, audio_shu_name
14
15
16
四、提取收录小说真实音频地址的链接地址
1 def get_audio_temp_url(self, html_str2):
2 """
3 提取含有小说真实地址的url的方法
4 :param html_str2:
5 :return:
6 """
7 html = parsel.Selector(html_str2)
8 audio_temp_url = html.css('iframe::attr(src)').extract_first()
9 audio_temp_url = self.SHU_TEMP_URL.format(audio_temp_url)
10 return audio_temp_url
11
12
五、提取该地址下的真实音频数据地址
1 def get_audio_url(self, html_str3):
2 """
3 提取小说真实的url地址的方法
4 :param html_str3:
5 :return:
6 """
7 audio_url = re.findall("mp3:'(.*?)'", html_str3, re.S)[0]
8 if 'm4a' in audio_url:
9 return audio_url
10 else:
11 return audio_url + '.m4a'
12
13
六、保存音频数据
1 def down_audio(self, audio_url, audio_shu_name, num):
2 """
3 下载有声小说的方法
4 :param audio_url:
5 :param audio_shu_name:
6 :param num:
7 :return:
8 """
9 path = f'{audio_shu_name}'
10 isExists = os.path.exists(path)
11 file_path = os.path.join(path, f'{audio_shu_name}_{num}.mp3')
12 if not isExists:
13 os.makedirs(path, exist_ok=True)
14 urlretrieve(audio_url, file_path)
15 print(f"{audio_shu_name}_{num}---下载完成")
16 else:
17 urlretrieve(audio_url, file_path)
18 print(f"{audio_shu_name}_{num}---下载完成")
19
20
七、实现逻辑思想的代码
1 def run(self):
2 """
3 实现主要逻辑思路
4 :return:
5 """
6 # 1.发送请求,获取响应数据
7 html_str = self.parse_url(self.SHU_URL, self.headers)
8 # 2.提取小说章节的url
9 chapter_urls, audio_shu_name = self.get_chapter_url(html_str)
10 tqdm_chapter_urls = tqdm(chapter_urls)
11 for num, chapter_url in enumerate(tqdm_chapter_urls):
12 # 3.对小说章节url发送请求,获取响应数据
13 html_str2 = self.parse_url(chapter_url, self.headers)
14 # 4.提取含有小说真实地址的url
15 audio_temp_url = self.get_audio_temp_url(html_str2)
16 # 5.对这个url地址发送请求,获取响应数据
17 html_str3 = self.parse_url(audio_temp_url, self.headers)
18 # 6.提取真实的url地址
19 audio_url = self.get_audio_url(html_str3)
20 # 7.下载小说
21 self.down_audio(audio_url, audio_shu_name, num + 1)
22
23
完成效果展示: