社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

抖音上超好听的神曲音乐,Python教你一次性下载

华为云开发者社区 • 5 年前 • 641 次点击  
阅读 15

抖音上超好听的神曲音乐,Python教你一次性下载

不知道什么时候开始,中国出现了南抖音、北快手的互文格局(东市买骏马,西市买鞍鞯…)。刚才提到了,之前比较喜欢刷抖音,对于我这种佛系程序猿,看网上这些整容妹子基本一个样。喜欢抖音主要是两个初衷,学做菜听音乐。朋友之前常说,人家抖音看妹子看的乐呵呵,你看人家做菜也能津津有味,一个人在那儿傻笑…民以食为天,我看到色香味俱全的菜,做的那么好吃的乐呵乐呵还不行么。

抖音捧红了很多人,也让很多本不怎么让大家熟知的歌曲、BGM,经过翻唱、混剪与视频搭配,从而传播大街小巷。什么“若不是你,突然闯进我心里…”亦或者“也许未来遥远在光年之外,我愿守候未知里为你等待…”,成了大家闲时在嘴边哼唱的调调。那么,有没有想过将这些好听的剪辑批量下载下来呢?

Python 链接抖音

python下载抖音内容的帖子网上有一些,但都比较麻烦,需要通过adb连接安卓手机后,模拟操作。我这么懒,这种事儿玩不来…那么,该如何获取抖音内容呢?网上搜了下大概有两种方式,一个是浏览器插件快抖,另外一个是我今天要说的抖音网页版。其实这两者差别不是很大,都是先将抖音内容下载至服务器后,通过开发简单网站配置域名后,让大家访问。让我们来看看抖音网页版

哎哟吼,居然看到了昨天爬虫的“乔奶奶”…当然今天的重点不是视频,而是下载它全站所有的音乐

爬虫实现分析

  • 热歌榜内容

大家先开看看这个抖音热歌榜歌曲,每页20首歌曲,一个55页。但细不细心大家都能发现,很多歌曲存在重复的问题。所以,等下爬虫的时候,我们需要先准备一个music_list,用来识别这首歌曲是否已经下载过了…

  • 网页解析

网页比较简单,一个div中包裹了一个ul>li*20,我们是不是该这样获取:

soup.find('div',{"class":"pull-left"}).find('ul').findAll('a')复制代码

如果你说是,那么一定没有好好看我前天整理的文章通过哪吒豆瓣影评,带你分析python爬虫快速入门:www.jianshu.com/p/ae38f7607…,我在文章中专门提到了一个小技巧,通过使用attr的属性进行快速解析,那么最快速的获取方式是:

soup.findAll('a', attrs={'onclick': True})复制代码

我们只需要获取所有的a标签,切这些标签中包含onclick这个属性即可。

  • 巧用eval

我们解析到的内容通过attr[‘onclick’],可以得到他的属性open1(‘夜’,’p9-dy.byteimg.com/obj/61a2000…),如何能快速获取歌曲名字和url呢?这里我们需要用到一个eval的小技巧:

index = "open1('夜','http://p9-dy.byteimg.com/obj/61a20007a98954b0831d','')"
index[5:]
"('夜','http://p9-dy.byteimg.com/obj/61a20007a98954b0831d','')"
index_tuple = eval(index[5:])
print(index_tuple, type(index_tuple))
('夜', 'http://p9-dy.byteimg.com/obj/61a20007a98954b0831d', '') <class 'tuple'>
index_tuple[0]
'夜'
index_tuple[1]
'http://p9-dy.byteimg.com/obj/61a20007a98954b0831d'复制代码

ps:今天一个朋友说我写代码没注释,我这是现身说法的告诉你,如何能写出让别人压根看不懂的代码,就是不写注释啊,哈哈!其实,代码我都在文章中一点一点的讲解了,所以没有写,但秉承着害怕大佬们取关的心态,我还是把注释加上吧…

代码实现

总体来说实现比较简单,全部代码如下:

# -*- coding: utf-8 -*-
# @Author   : 王翔
# @JianShu  : 清风Python
# @Date     : 2019/7/31 23:25
# @Software : PyCharm
# @version  :Python 3.7.3
# @File     : DouYinMusic.py

import os
import requests
from bs4 import BeautifulSoup
import threading
import time


class DouYinMusic:
    def __init__(self):
        self.music_list = []
        self.path = self.download_path()

    @staticmethod
    def download_path():
        """
        获取代码执行目录,并在目录下创建Music文件夹
        :return Music文件夹全路径
        """
        base_dir = os.path.dirname(os.path.abspath(__file__))
        _path = os.path.join(base_dir, "Music")
        if not os.path.exists(_path):
            os.mkdir(_path)
        return _path

    def get_request(self, url):
        """
        封装requests.get方法
        如果为网页请求,返回网页内容
        否则,解析音乐地址,并返回音乐二进制文件
        :param url: 请求url(分网页、音乐两类)
        :return: 网页内容 & 音乐二进制文件
        """
        r = requests.get(url, timeout=5)
        if url.endswith('html'):
            return r.text
        else:
            return r.content

    def analysis_html(self, html):
        """
        根据获取的网页内容,解析音乐名称、下载地址
        调用音乐下载方法
        :param html: 网页内容
        """
        soup = BeautifulSoup(html, 'lxml')
        # 根据关键字onclick查找每个下载地址
        for tag_a in soup.findAll('a', attrs={'onclick': True}):
            # 下载格式'("name","link","")',通过eval将str转化为tuple类型
            link_list = eval(tag_a['onclick'][5:])
            music_name, music_link = link_list[:2]
            # 因为存在部分重复音乐,故设置判断下载过的音乐跳过
            if music_name in self.music_list:
                continue
            self.music_list.append(music_name)
            t = threading.Thread(target=self.download_music, args=(music_name, music_link))
            time.sleep(0.5)
            t.start()

    def download_music(self, music_name, music_link):
        """
        解析音乐文件,完成音乐下载
        :param music_name: 音乐名称
        :param music_link: 下载地址
        """
        _full_name = os.path.join(self.path, music_name)
        with open(_full_name + '.mp3', 'wb') as f:
            f.write(self.get_request(music_link))
        print("抖音音乐:{} 下载完成".format(music_name))

    def run(self):
        """
        主方法,用于批量生成url
        """
        for page in range(1,55):
            url = "http://douyin.bm8.com.cn/t_{}.html".format(page)
            html = self.get_request(url)
            self.analysis_html(html)


if


    
 __name__ == '__main__':
    main = DouYinMusic()
    main.run()复制代码

来让我们看看效果吧:

网站是通过nginx负载均衡搭建的,有一些链接已经失效了。最终下载了不重复的592首抖音音乐

同样的,大家喜欢可以按照这种方法,尝试下载一下网站的抖音视频。

本文作者华为云 | 清风Python


点击关注,第一时间了解华为云新鲜技术~


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/70900
 
641 次点击