·「python爬虫入门」网易云音乐下载

2015-6-2

今天把昨天Git上看的一个下载网易云音乐歌单歌曲的脚本尝试看懂并修改

Git地址:https://github.com/keli/netease-music

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import urllib2
import json
import os
import sys
import md5
import string
import random

# Set cookie
cookie_opener = urllib2.build_opener()
cookie_opener.addheaders.append((‘Cookie‘, ‘appver=2.0.2‘))
cookie_opener.addheaders.append((‘Referer‘, ‘http://music.163.com‘))
urllib2.install_opener(cookie_opener)

def encrypted_id(id):
    byte1 = bytearray(‘3go8&$8*3*3h0k(2)2‘)
    byte2 = bytearray(id)
    byte1_len = len(byte1)
    for i in xrange(len(byte2)):
        byte2[i] = byte2[i]^byte1[i%byte1_len]
    m = md5.new()
    m.update(byte2)
    result = m.digest().encode(‘base64‘)[:-1]
    result = result.replace(‘/‘, ‘_‘)
    result = result.replace(‘+‘, ‘-‘)
    return result

def get_playlist(playlist_id):
    url = ‘http://music.163.com/api/playlist/detail?id=%s‘ % playlist_id
    resp = urllib2.urlopen(url)
    data = json.loads(resp.read())
    return data[‘result‘]

def save_track(track, folder, position):
    name = track[‘hMusic‘][‘name‘]

    if position < 10:
        pos = "0%d" % position
    else:
        pos = "%d" % position

    #fname = pos + ‘ ‘ + name + track[‘hMusic‘][‘extension‘]
    fname = name + ‘.‘ + track[‘hMusic‘][‘extension‘]
    fname = string.replace(fname, ‘/‘, ‘_‘)
    fpath = os.path.normpath(os.path.join(folder, fname))

    if os.path.exists(fpath):
        return

    print "Downloading", fpath, "..."

    dfsId = str(track[‘hMusic‘][‘dfsId‘])
    url = ‘http://m%d.music.126.net/%s/%s.%s‘ % (random.randrange(1, 3), encrypted_id(dfsId), dfsId, track[‘hMusic‘][‘extension‘])
    resp = urllib2.urlopen(track[‘mp3Url‘])
    data = resp.read()
    resp.close()

    with open(fpath, ‘wb‘) as mp3:
      mp3.write(data)

def download_playlist(playlist_id, folder=‘.‘):
    playlist = get_playlist(playlist_id)

    name = playlist[‘name‘]
    folder = os.path.join(folder, name)

    if not os.path.exists(folder):
        os.makedirs(folder)

    for idx, track in enumerate(playlist[‘tracks‘]):
        save_track(track, folder, idx+1)

if __name__ == ‘__main__‘:
    if len(sys.argv) < 2:
        print "Usage: %s <playlist id>" % sys.argv[0]
        sys.exit(1)
    download_playlist(sys.argv[1])

这边是对cookie的处理,addheaders的方法之前没有看到过,help查询居然也没有查到,但是有用

cookie_opener = urllib2.build_opener()
cookie_opener.addheaders.append((‘Cookie‘, ‘appver=2.0.2‘))
cookie_opener.addheaders.append((‘Referer‘, ‘http://music.163.com‘))
urllib2.install_opener(cookie_opener)

这一段其实是没有用的,但是挺好奇这段代码里面函数的作用,过段时间再去学一下

def encrypted_id(id):
    byte1 = bytearray(‘3go8&$8*3*3h0k(2)2‘)
    byte2 = bytearray(id)
    byte1_len = len(byte1)
    for i in xrange(len(byte2)):
        byte2[i] = byte2[i]^byte1[i%byte1_len]
    m = md5.new()
    m.update(byte2)
    result = m.digest().encode(‘base64‘)[:-1]
    result = result.replace(‘/‘, ‘_‘)
    result = result.replace(‘+‘, ‘-‘)
    return result

下面这段代码是发挥主要作用的,但是这个脚本是原作者三个月前写的,网易云音乐应该有一些变化

def get_playlist(playlist_id):
    url = ‘http://music.163.com/api/playlist/detail?id=%s‘ % playlist_id
    resp = urllib2.urlopen(url)
    data = json.loads(resp.read())
    return data[‘result‘]

def save_track(track, folder, position):
    name = track[‘hMusic‘][‘name‘]

    if position < 10:
        pos = "0%d" % position
    else:
        pos = "%d" % position

    #fname = pos + ‘ ‘ + name + track[‘hMusic‘][‘extension‘]
    fname = name + ‘.‘ + track[‘hMusic‘][‘extension‘]
    fname = string.replace(fname, ‘/‘, ‘_‘)
    fpath = os.path.normpath(os.path.join(folder, fname))

    if os.path.exists(fpath):
        return

    print "Downloading", fpath, "..."

    dfsId = str(track[‘hMusic‘][‘dfsId‘])
    url = ‘http://m%d.music.126.net/%s/%s.%s‘ % (random.randrange(1, 3), encrypted_id(dfsId), dfsId, track[‘hMusic‘][‘extension‘])
    resp = urllib2.urlopen(track[‘mp3Url‘])
    data = resp.read()
    resp.close()

    with open(fpath, ‘wb‘) as mp3:
      mp3.write(data)

def download_playlist(playlist_id, folder=‘.‘):
    playlist = get_playlist(playlist_id)

    name = playlist[‘name‘]
    folder = os.path.join(folder, name)

    if not os.path.exists(folder):
        os.makedirs(folder)

    for idx, track in enumerate(playlist[‘tracks‘]):
        save_track(track, folder, idx+1)

首先是JSON,我之前并没有学过JSON,XML也只是昨天看了一小会儿

http://music.163.com/api/playlist/detail?id=4566307 打开准备下载的歌单

用Firebug看Json挺清晰,结构都很清楚,chrome就感觉有点一堆凑一起

看代码也知道歌曲的链接在tracks里面

我按着原作者的代码调试 发现一直卡在

name = track[‘hMusic‘][‘name‘]

后来调了半天,才去JSON文件里看了,发现tracks里面不是所有歌曲都有 hMusic 这个 属性

后来直接改成  name = track[‘name‘]

而且再仔细看JSON 发现代码有好几处不对的地方 最后改成了这样

ef get_playlist(playlist_id):
    url = ‘http://music.163.com/api/playlist/detail?id=%s‘ % playlist_id
    resp = urllib2.urlopen(url)
    data = json.loads(resp.read())
    print data[‘result‘][‘name‘]
    return data[‘result‘]

def save_track(track, folder, position):
    name = track[‘name‘] #name = track[‘hMusic‘][‘name‘]
    print name
    if position < 10:
        pos = "0%d" % position
    else:
        pos = "%d" % position

    #fname = pos + ‘ ‘ + name + track[‘hMusic‘][‘extension‘]
    fname = name + str(position) + ‘.mp3‘ #fname = name + str(position) + ‘.‘ + track[‘hMusic‘][‘extension‘]
    fname = string.replace(fname, ‘/‘, ‘_‘)
    fpath = os.path.normpath(os.path.join(folder, fname))

    if os.path.exists(fpath):
        return
    print "Downloading", fpath, "..."

    # dfsId = str(track[‘hMusic‘][‘dfsId‘])
    # url = ‘http:/7m%d.music.126.net/%s/%s.%s‘ % (random.randrange(1, 3), encrypted_id(dfsId), dfsId, track[‘hMusic‘][‘extension‘])
    try:
        resp = urllib2.urlopen(track[‘mp3Url‘], timeout = 5)
        data = resp.read()
        resp.close()
    except urllib2.URLError as e:
        print type(e)    #not catch
        pass
    except socket.timeout as e:
        print type(e)    #catched
        pass
    else:
        with open(fpath, ‘wb‘) as mp3:
            mp3.write(data)

def download_playlist(playlist_id, folder=‘.‘):
    playlist = get_playlist(playlist_id)

    name = playlist[‘name‘]
    folder = os.path.join(folder, name)

    if not os.path.exists(folder):
        os.makedirs(folder)

    for idx, track in enumerate(playlist[‘tracks‘]):
        print ‘begin save‘
        save_track(track, folder, idx+1)

注释掉的部分就是更改的地方

在下载歌曲的时候,经常会卡在一个地方,然后知道urlopen可以设置timeout 就是超时时间,

然后我的想法是超时的话就报错然后继续下载下一首

但是不是很熟悉try except 试了好久

试过好几个版本

 try:
        resp = urllib2.urlopen(track[‘mp3Url‘], timeout = 5)
        data = resp.read()
        resp.close()
    except urllib2.URLError as e:
        print type(e)    #not catch
        pass
    except socket.timeout as e:
        print type(e)    #catched
        pass  

with open(fpath, ‘wb‘) as mp3:
    mp3.write(data)
 try:
        resp = urllib2.urlopen(track[‘mp3Url‘], timeout = 5)
        data = resp.read()
        resp.close()
    except urllib2.URLError as e:
        print type(e)    #not catch
    except socket.timeout as e:
        print type(e)    #catched
    else:
        with open(fpath, ‘wb‘) as mp3:
            mp3.write(data)
 try:
        resp = urllib2.urlopen(track[‘mp3Url‘], timeout = 5)
    except urllib2.URLError as e:
        print type(e)    #not catch
        pass
    except socket.timeout as e:
        print type(e)    #catched
        pass
data = resp.read()
resp.close()
with open(fpath, ‘wb‘) as mp3:
    mp3.write(data)

总之都是代码报错,报错了也没有继续运行下去

后来改成这样

    try:
        resp = urllib2.urlopen(track[‘mp3Url‘], timeout = 5)
        data = resp.read()
        resp.close()
    except urllib2.URLError as e:
        print type(e)    #not catch
        pass
    except socket.timeout as e:
        print type(e)    #catched
        pass
    else:
        with open(fpath, ‘wb‘) as mp3:
            mp3.write(data)

就行了=。=, 还是得再好好看看异常处理那一块

总之这就是一下午的学习,虽然下歌什么的对我并没有什么卵用

时间: 2024-10-14 13:05:25

·「python爬虫入门」网易云音乐下载的相关文章

使用webcollector爬虫技术获取网易云音乐全部歌曲

最近在知乎上看到一个话题,说使用爬虫技术获取网易云音乐上的歌曲,甚至还包括付费的歌曲,哥瞬间心动了,这年头,好听的流行音乐或者经典老歌都开始收费了,只能听不能下载,着实很郁闷,现在机会来了,于是开始研究爬虫技术,翻阅各种资料,最终选择网友们一致认为比较好用的webcollector框架来实现. 首先,我们来认识一下webcollector,webcollector是一个无需配置,便于二次开发的爬虫框架,它提供精简的API,只需少量代码即可实现一个功能强大的爬虫,webcollector+hado

网易云音乐下载|网易云音乐电脑版下载

据记忆开始接触音乐软件的时候就是酷狗音乐,后来慢慢发现周围的人都是用网易云音乐.之前没有很在意,随着朋友圈分享歌曲越来越多的来自网易云音乐,自己忍不住也下载了看看.网易云音乐,感觉比较好的是界面相对比较整齐,不是很凌乱.另外就是私人FM,推荐的一些歌曲,大部分都是比较合胃口的.网易云音乐下载链接软件介绍网易云音乐是网易推出的一款音乐产品,依托专业音乐人.DJ.好友推荐及社交功能,在线音乐服务主打歌单.社交.大牌推荐和音乐指纹,以歌单.DJ节目.社交.地理位置为核心要素,主打发现和分享.网易云音乐

如何用Python网络爬虫爬取网易云音乐歌词

前几天小编给大家分享了数据可视化分析,在文尾提及了网易云音乐歌词爬取,今天小编给大家分享网易云音乐歌词爬取方法. 本文的总体思路如下: 找到正确的URL,获取源码: 利用bs4解析源码,获取歌曲名和歌曲ID: 调用网易云歌曲API,获取歌词: 将歌词写入文件,并存入本地. 本文的目的是获取网易云音乐的歌词,并将歌词存入到本地文件.整体的效果图如下所示: 基于Python网易云音乐歌词爬取 赵雷的歌曲 本文以民谣歌神赵雷为数据采集对象,专门采集他的歌曲歌词,其他歌手的歌词采集方式可以类推,下图展示

Python爬一爬网易云音乐

结果 对过程没有兴趣的童鞋直接看这里啦. 评论数大于五万的歌曲排行榜 首先恭喜一下我最喜欢的歌手(之一)周杰伦的<晴天>成为网易云音乐第一首评论数过百万的歌曲! 通过结果发现目前评论数过十万的歌曲正好十首,通过这前十首发现: 薛之谦现在真的很火啦~ 几乎都是男歌手啊,男歌手貌似更受欢迎?(别打我),男歌手中周杰伦.薛之谦.许嵩(这三位我都比较喜欢)几乎占了榜单半壁江山... <Fade>电音强势来袭,很带感哈(搭配炫迈写代码完全停不下来..) 根据结果做了网易云音乐歌单 : 评论数

使用爬虫抓取网易云音乐热门评论生成好玩的词云

互联网爬虫是一个很有意思的技术,借由爬虫,我们可以做到很多好玩的事情--这其中就包括爬取评论. 词云就是个更好玩的技术,通过技术方法分析词语出现频率,生成可视化的图形,将文字内容用图形呈现,想想就很意思. 这次,我们就试着把这两个技术结合起来吧. 前言 网易云音乐一直是我向往的"神坛",听音乐看到走心的评论的那一刻,高山流水.于是今天来抓取一下歌曲的热门评论.并做成词云来展示,看看相对于这首歌最让人有感受的评论内容是什么. 做成词云的好处就是直观以及美观, 其他的我也想不出来有什么了.

将 QQ 音乐、网易云音乐和虾米音乐资源「整合」一起的Chrome 扩展Listen 1

原文地址:http://whosmall.com/?post=418 本文标签: Chrome扩展 Chrome浏览器 Chrome扩展Listen1 音乐资源整合 Listen1安装方法 在 Chrome 上安装了这款名为 Listen 1 的插件,妈妈可是再也不用担心你找不到想听的歌了.它将 QQ 音乐.网易云音乐以及虾米音乐的音乐资源「整合」在了一起,你只需要输入音乐关键词,就可以方便地三大曲库中跳转搜索. 安装方法 Listen 1 的安装方法与一般的 Chrome Extension

Java 爬虫入门(网易云音乐和知乎实例)

最近公司赶项目,过上了996的生活,周日还要陪老婆,实在没时间静下来写点东西,于是导致了swift编写2048的第三篇迟迟没有开工,在此说声抱歉,尽量抽时间在这周末补出来. 首先来介绍下爬虫的作用,爬虫主要用于大批量抓取网站中我们所需数据,其实就是模拟出http请求,之后解析分析所得的数据获取我们需要的信息的这么一个过程. 由于网上已经有很多现成的爬虫框架了,这里就不重复造轮子了,先给大家说一下原理,大家可以自己尝试写一个,至于具体实现这篇只带来一个框架的使用实例,让大家可以根据例子快速写出所需

Python 获取网易云音乐热门评论

--> html { line-height: 1.6 } body { font-family: -apple-system-font, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; background-color: #f3f3f3; line-height: inherit } body.ric

关于网易云音乐爬虫的api接口?

抓包能力有限,分析了一下网易云音乐的一些api接口,但是关于它很多post请求都是加了密,没有弄太明白.之前在知乎看到过一个豆瓣工程师写的教程,但是被投诉删掉了,请问有网友fork了的吗?因为我觉得他写的代码都比较pythonic,符合pep8规范.知乎另外几名大V比如@路人甲虽然经常分享数据,但是很少分享源代码,github也没有公布,公开过的代码我觉得他很多基础的pep8细节都忽略了,而且他的爬虫的效率非常低,比如爬网易10k+评论,在专栏说爬了6个小时之类的很辛苦之类的话,但是看他的代码别