python爬取音悦台MV+进度条下载

220 阅读4分钟

音悦Tai,创立于2009年,是一家专注于高清MV在线欣赏与传播的音乐分享平台。跟紧新歌发片速度,通过筛选网友提供的内容,第一时间为用户呈现MV作品。音悦Tai还是广大的MV爱好者的社交网络平台,在音悦Tai建设“我的家”,把自己的最爱MV、悦单秀给大家,以找到志趣相投的悦友。

​我们的目标是通过使用Python的requests库实现mv的下载,然后到本地播放!实现输入或复制音悦台当前播放的MV链接到程序中,即可实现MV的下载。 环境:python3.7 pycharm  

第一步:打开音悦台的任何页面,然后快捷键按F12,可以出现开发者工具 ​

 这时候刷新下页面,可以看到下侧列表有很多资源

​编辑

我们的思路是找到视频的播放链接地址,然后打开再写入本地文件,所以需要在里面找到有用的东西,通过认真寻找找到有个链接的返回有如下信息,可以点开Response,但是json格式,这里我们点开Preview预览可以看到如下相关的MV信息,里面有个videoUrl,这里就是我们要的播放链接:

​编辑

第二步:通过requests库实现代码端的访问,然后将此链接的返回转成json格式,也就是python的反序列化数据,让其读入内存中

import requests
import json

url = 'https://www.yinyuetai.com/play?id=151'
mvid = url.split('=')[-1]
info_url = 'https://data.yinyuetai.com/video/getVideoInfo?id={}'.format(mvid)
headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Sa'
}
res = requests.get(info_url)
html = res.text
print(html)
mv_url = json.loads(html)['videoUrl']
mv_name = json.loads(html)['videoName']
print(mv_url)
print(mv_name)

 返回结果如下:​编辑

 第三步:既然播放链接已经拿到了,现在是不是可以直接请求了,我试了如下:

response = requests.get(mv_url, headers=headers, stream=True)
print(response)

​编辑

浏览器直接访问也是403,按理说这个链接是可以直接访问的,但是却报了403

​编辑

 经过查询资料发现这是网站做了反爬措施,增加了防盗链的设置,因此我们的请求头除了包含浏览器的参数外,还需要包含referer的请求头,这样网站就可以识别你的请求是从此网站内部跳转过来的。​编辑

 headers增加referer参数后如下:

headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Sa'
        , 'Referer': 'https://www.yinyuetai.com/'}

再次请求为200

​编辑

 第四步:既然请求正常后,现在就是要去打开视频播放链接,然后写入本地文件,这里的请求需要注意的是要加上stream=True参数

response = requests.get(mv_url, headers=headers, stream=True)

查阅资料相关解释如下:

​编辑

第五步:就是把这个请求的返回二进制内容写入到本地文件,文件以mv的名字命名,这里代码略,请看最终代码。

因为是下载所以最好有进度条看起来方便,我写了两种进度条供大家选择,都可正常运行,如果你需要使用其中一种,请注意代码的注释,或者将其封装成方法去调用也可,最终代码如下:

# Author:Nebula
import json
import os
import sys
from contextlib import closing
import requests
from tqdm import tqdm


def download_mv(url):
    mvid = url.split('=')[-1]
    info_url = 'https://data.yinyuetai.com/video/getVideoInfo?id={}'.format(mvid)
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Sa'
        , 'Referer': 'https://www.yinyuetai.com/'}
    # 参考视频请求报403的原因 https://www.jianshu.com/p/d907f9f6bb2c 这里加上Referer
    res = requests.get(info_url)
    html = res.text
    print(html)
    mv_url = json.loads(html)['videoUrl']
    mv_name = json.loads(html)['videoName']
    # print(mv_url)
    response = requests.get(mv_url, headers=headers, stream=True)
    # # print(response.status_code)
    # # print(response.headers['content-length'])
    #
    # 新建一个文件夹
    if not os.path.exists('D:/音悦台mv'):
        os.mkdir('D:/音悦台mv')

    # 简易进度条  参考链接:https://www.cnblogs.com/zhuminghui/p/13985315.html
    n = 1
    content_size = int(response.headers['content-length'])
    if response.status_code == 200:
        with open('D:/音悦台mv/{}.mp4'.format(mv_name), "wb") as f:
            for i in response.iter_content(chunk_size=1024):
                rate = n * 1024 / content_size
                print("\r", end="")
                print("《{0}》大小:{1}MB 下载进度:{2:%}".format(mv_name,int(content_size/1024/1024),rate), "▋"*(n//2048), end="")
                sys.stdout.flush()
                f.write(i)
                n += 1
            print("下载完成")

    # 带自更新进度的进度条  进度条参考链接:https://www.jb51.net/article/227211.htm
    # with closing(requests.get(mv_url, stream=True)) as res:
    #     total_size = int(res.headers['content-length'])
    #     if res.status_code == 200:
    #         with open('D:/音悦台mv/{}.mp4'.format(mv_name), "wb") as f,tqdm(
    #                 desc=mv_name,  # 进度条的前面的提示
    #                 total=total_size,  # 迭代元素的多少
    #                 unit='B',  # 用来定义每个迭代单元的字符串。默认为"it",表示每个迭代;在下载或解压时,设为"B",代表每个“块”。
    #                 unit_scale=True,  # 如果设置为1或者True,迭代数量就会被自动减少或者重置,且将在国际单位制标准后面添加一个度量前缀(kilo、mega等)[默认:False]
    #                 unit_divisor=1024,  # float, optional:默认为1000
    #         ) as progressbar:
    #             for chunk in res.iter_content(chunk_size=1024):
    #                 if chunk:
    #                     f.write(chunk)
    #                     progressbar.update(1024)


if __name__ == '__main__':
    # url = input('Enter the mv url you want to download:')
    url = 'https://www.yinyuetai.com/play?id=153'
    download_mv(url)

 最终效果如下:

(简易进度条)下载中:

​编辑

(简易进度条)下载完成:

​编辑 ​编辑

可以正常进行播放:

​​​编辑​