Python爬虫实践 —— 4.好听音乐网轻音乐资源下载

Stella981
• 阅读 956

第三章的requests库阶段性demo,爬取好听音乐网的榜上歌曲。

此网站没有js混淆,音乐资源链接有规律,适合爬虫新手上手。

首先观察首页和音乐榜的url链接关系,我们先手动模拟下载,chrome f12获取response,可探查到url规律如下:

Python爬虫实践 —— 4.好听音乐网轻音乐资源下载

Python爬虫实践 —— 4.好听音乐网轻音乐资源下载

热播榜url为:

http://www.htqyy.com/top/hot

新曲榜url为:

http://www.htqyy.com/top/new

由此可知hot、new、recommend、latest、gedan分别为各榜二级网址

2.再分析hot榜单内页码网址规律

Python爬虫实践 —— 4.好听音乐网轻音乐资源下载

可得url规律为:{index}榜第 i 页网址为 http://www.htqyy.com/top/musicList/{index}?pageIndex=(i-1)&pageSize=20

3.接着找下载链接规律

在试听界面点击试听按钮,f12刷新 network media会获得media音频response,statu code显示为206,说明歌曲get请求已缓存到disk,验证url规律为http://f2.htqyy.com/play7/sid/mp3/12,试听和下载url的关联关系,其中sid,也就是歌曲名为主键,所以我们从音乐榜页码页获得的sid可以传入下载地址中,拼接获得下载地址,/mp3/12为固定字符串

其后我在运行爬虫的时候发现部分资源会401,找到对应的sid页面,f12排查,发现下载地址并不唯一,按mp3和m4a文件类型分别有两个地址:

http://f2.htqyy.com/play7/{sid}/mp3/12http://f2.htqyy.com/play7/{sid}/m4a/12

Python爬虫实践 —— 4.好听音乐网轻音乐资源下载

Python爬虫实践 —— 4.好听音乐网轻音乐资源下载

实际运行爬虫的时候,我们会发现经常有歌曲无法200正常下载,或者401或者抛出异常我自己分析的话,这有两种原因,

1.mp3格式url网址无效,需切换m4a网址下载

2.请求时间间隔太短,应设置1-2s,以防因为延迟和服务器原因无法正常爬取。

此demo主要考察python和程序设计基本功,requests库的应用较少,由此也发现异常处理、网址拼接、f12工具的使用、性能和代码质量考核等因素在爬虫设计时是非常重要的,由此也看出一个设计优异的爬虫框架对实际业务来说是非常重要的,连续爬取、防封、分布式爬取,提高性能门槛也是必须的业务要求,爬虫随便几个demo写完看似很简单,但是简单的事如何做的有质量也是不简单的。

具体代码如下:

# SweetLightSpider
import re   # python 的正则库
import requests     # python 的requests库
import time
import random       # 随机选择
from requests import exceptions  # requests 内置exception


class SweetLightMusicSpider:

    def __init__(self, page):
        self.page = page

# 随机获取音乐榜单的网页信息text数据,取得songID准备为后续url拼接,获得songName获得歌曲名
    def __getSong(self):
        songID = []
        songName = []
        keyword = ["hot", "new", "recommend", "latest", "gedan"]
        rankform = random.choice(keyword)
        print(rankform)
        for i in range(0, self.page):
            url = "http://www.htqyy.com/top/musicList/"+str(rankform)+"?pageIndex="+str(i)+"&pageSize=20"
            # 获得带有音乐id和name的信息的html文本
            html = requests.get(url)
            strr = html.text

            #正则匹配筛选信息
            pat1 = r'title="(.*?)" sid'
            pat2 = r'sid="(.*?)"'

            id_list = re.findall(pat2, strr)
            title_list = re.findall(pat1, strr)
            
            # 获得songID/Name数组
            songID.extend(id_list)
            songName.extend(title_list)
        return songID, songName

    def __songdownload(self):
        song_list = SweetLightMusicSpider.__getSong(self)
        for x in range(0, len(song_list[0])):
            song_url = "http://f2.htqyy.com/play7/"+str(song_list[0][x])+"/"+"mp3"+"/12"
            song_name = song_list[1][x]

            response = requests.get(song_url)
            print(response.status_code)
            data = response.content

            if response.status_code == 200:

                print("正在下载第{0}首, 歌曲名为:《{1}》".format(x+1, song_name))
                with open("E:\\music\\{}.mp3".format(song_name), "wb") as f:
                    f.write(data)
                print("第{0}首: 《{1}》 已下载完毕".format(x+1, song_name))

            elif response.status_code == 401:
                time.sleep(2)
                print("重定向资源中")
                song_url2 = "http://f2.htqyy.com/play7/"+str(song_list[0][x])+"/"+"m4a"+"/12"
                response2 = requests.get(song_url2)
                print(response2.status_code)
                try:
                    assert response2.status_code == 200
                except exceptions.HTTPError as e:
                    print(e)
                    continue
                else:
                    data2 = response2.content
                    print("正在下载第{0}首, 歌曲名为:《{1}》".format(x + 1, song_name))
                    with open("E:\\music\\{}.mp3".format(song_name), "wb") as f:
                        f.write(data2)
                    print("第{0}首: 《{1}》 已下载完毕".format(x + 1, song_name))

        time.sleep(1)

    def music_Spider(self):
        SweetLightMusicSpider.__songdownload(self)


if __name__ == '__main__':
    i = SweetLightMusicSpider(10)
    i.music_Spider()

设置两个请求间隔为1s,重定向url为2s,调试如下,基本杜绝了

1.无法获取到的歌曲  2.下载错误为十几KB无法打开的歌曲  这两个运行异常bug

最后牺牲了部分爬取效率获得了爬取质量的提高:

Python爬虫实践 —— 4.好听音乐网轻音乐资源下载

最后检查E盘的音乐下载情况,没有下载错误,文件大小均在1-3mb,不存在音乐无法打开的情况

Python爬虫实践 —— 4.好听音乐网轻音乐资源下载

随便打开一首网易云播放器验证下:

Python爬虫实践 —— 4.好听音乐网轻音乐资源下载

没有问题,bingo。因为是轻音乐网站嘛,faded的纯乐器版。。。。。。i am faded  >_<

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这