Python爬蟲實(shí)踐-網(wǎng)易云音樂

1眼姐、前言

最近诅迷,網(wǎng)易的音樂很多聽不到了,剛好也看到很多教程众旗,跟進(jìn)學(xué)習(xí)了一下罢杉,也集大全了吧,本來想優(yōu)化一下的贡歧,但是發(fā)現(xiàn)問題還是有點(diǎn)復(fù)雜滩租,最后另辟捷徑,提供了簡(jiǎn)單的方法袄洹律想!

本文主要參考 python編寫GUI版網(wǎng)易云音樂爬蟲 后改寫,有興趣的可以看看文章的GUI绍弟,了解更多知識(shí)~

2技即、Python + 爬蟲

首先,說一下準(zhǔn)備工作:

  • Python:需要基本的python語法基礎(chǔ)
  • requests:專業(yè)用于請(qǐng)求處理晌柬,requests庫學(xué)習(xí)文檔中文版
  • lxml:其實(shí)可以用pythonth自帶的正則表達(dá)式庫re姥份,但是為了更加簡(jiǎn)單入門,用 lxml 中的 etree 進(jìn)行網(wǎng)頁數(shù)據(jù)定位爬取年碘。
  • re:python正則表達(dá)式處理
  • json:python的json處理庫

如果大家對(duì)上面的庫還比不懂,可以看看我的之前文章 《Python爬蟲實(shí)踐入門篇》

然后展鸡,說一下我們現(xiàn)在已經(jīng)知道下載鏈接是這樣的:

http://music.163.com/song/media/outer/url?id='

id 就是歌曲的id屿衅!

所以,現(xiàn)在我們爬蟲主要的工作就是找到這個(gè)id莹弊,當(dāng)然為了更好的保存涤久,也要找到這個(gè)歌名啦涡尘!

那現(xiàn)在就是要找到我們需要爬蟲的網(wǎng)站鏈接啦!我分析了一下响迂,大概是下面三種:

#歌曲清單
music_list = 'https://music.163.com/#/playlist?id=2412826586' 
#歌手排行榜
artist_list = 'https://music.163.com/#/artist?id=8325'
#搜索列表 
search_list = 'https://music.163.com/#/search/m/?order=hot&cat=全部&limit=435&offset=435&s=梁靜茹' 

如果你已經(jīng)只是想下載一首歌考抄,比如靜茹-勇氣:https://music.163.com/#/song?id=254485,那你直接就用瀏覽器打開 http://music.163.com/song/media/outer/url?id=254485 就可以了蔗彤,沒必要爬蟲按贰!

好啦然遏!感覺重點(diǎn)都說完了贫途,提取和解析就是用 lxml,不懂的就看我之前的文章啊 《Python爬蟲實(shí)踐入門篇》

3待侵、下載歌詞

如果還要下載歌詞丢早,那也很簡(jiǎn)單,通過接口秧倾,有歌曲的id就可以:

url = 'http://music.163.com/api/song/lyric?id={}&lv=-1&kv=-1&tv=-1'.format(song_id)

返回的json數(shù)據(jù)大概長(zhǎng)這樣:

{
    sgc: true,
    sfy: false,
    qfy: false,
    lrc:
    {
        version: 7,
        lyric: "[00:39.070]開了窗 等待天亮\n[00:46.160]看這城市 悄悄的 熄了光\n[00:51.850]聽風(fēng)的方向\n[00:55.090]這一刻 是否和我一樣\n[00:58.730]孤單的飛翔\n[01:02.300]模糊了眼眶\n[01:07.760]廣播里 那首歌曲\n[01:14.830]重復(fù)當(dāng)時(shí) 那條街那個(gè)你\n[01:20.410]相同的桌椅\n[01:23.740]不用言語 就會(huì)有默契\n[01:27.470]這份親密\n[01:30.560]那么熟悉\n[01:33.850]在愛里 等著你\n[01:37.480]被你疼惜 有種暖意\n[01:41.090]在夢(mèng)里 全是你\n[01:43.920]不要再遲疑 把我抱緊"
    },
    klyric:
    {
        version: 0,
        lyric: null
    },
    tlyric:
    {
        version: 0,
        lyric: null
    },
    code: 200
}

剩下的也沒有什么好說的啦怨酝!

4、坑點(diǎn)與進(jìn)階

表面上很簡(jiǎn)單那先,但是需要注意的是农猬,網(wǎng)易返回的鏈接,數(shù)據(jù)是js動(dòng)態(tài)加載胃榕,也就是爬蟲得到的網(wǎng)頁數(shù)據(jù)和瀏覽器得到的dom內(nèi)容和結(jié)構(gòu)不一樣盛险!


  • 其中,搜索列表爬蟲回來的內(nèi)容勋又,完全得不到歌曲id?嗑颉!楔壤!

  • 解決
    解決方法也是有的鹤啡!

    • python模擬瀏覽器
      使用selenium+phantomjs無界面瀏覽器,這兩者的結(jié)合其實(shí)就是直接操作瀏覽器蹲嚣,可以獲取JavaScript渲染后的頁面數(shù)據(jù)递瑰。

    缺點(diǎn):

    由于是無界面瀏覽器,采用此方案效率極低隙畜,如果大批量抓取不推薦抖部。
    對(duì)于異步請(qǐng)求并且數(shù)據(jù)在源碼中并不存在的,同時(shí)也就無法抓取到的數(shù)據(jù)议惰。

    • 搜索的歌曲變成歌單
      比如想下載全部的某一歌手的全部音樂慎颗,用手機(jī)云音樂搜索,然后全部保存到新建一個(gè)歌單俯萎,這樣就可以啦!
  • 進(jìn)階
    如果想使用了解更多網(wǎng)易云音樂js的加密解密過程函卒,可以看看這個(gè) Python 爬蟲如何獲取 JS 生成的 URL 和網(wǎng)頁內(nèi)容? - 路人甲的回答 - 知乎

總結(jié)

用python撇眯,就一定要簡(jiǎn)單报嵌,我認(rèn)為復(fù)雜的東西叛本,還是盡量少做,能取巧就取巧来候,所以本文沒有使用selenium+phantomjs實(shí)踐跷叉,如果想了解更多selenium+phantomjs內(nèi)容,可以參考文末引用鏈接营搅。

注:本文只是技術(shù)交流,請(qǐng)不要商業(yè)用途~ 如有違反转质,本人一概不負(fù)責(zé)。

全部代碼

又是非常簡(jiǎn)單的100行代碼完事7锌荨B腹!

GitHub: WebCrawlerExample/163_NeteaseMusic.py at master · iHTCboy/WebCrawlerExample


import os
import re
import json
import requests
from lxml import etree


def download_songs(url=None):
    if url is None:
        url = 'https://music.163.com/#/playlist?id=2384642500'

    url = url.replace('/#', '').replace('https', 'http')  # 對(duì)字符串進(jìn)行去空格和轉(zhuǎn)協(xié)議處理
    # 網(wǎng)易云音樂外鏈url接口:http://music.163.com/song/media/outer/url?id=xxxx
    out_link = 'http://music.163.com/song/media/outer/url?id='
    # 請(qǐng)求頭
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
        'Referer': 'https://music.163.com/',
        'Host': 'music.163.com'
    }
    # 請(qǐng)求頁面的源碼
    res = requests.get(url=url, headers=headers).text

    tree = etree.HTML(res)
    # 音樂列表
    song_list = tree.xpath('//ul[@class="f-hide"]/li/a')
    # 如果是歌手頁面
    artist_name_tree = tree.xpath('//h2[@id="artist-name"]/text()')
    artist_name = str(artist_name_tree[0]) if artist_name_tree else None

    # 如果是歌單頁面:
    #song_list_tree = tree.xpath('//*[@id="m-playlist"]/div[1]/div/div/div[2]/div[2]/div/div[1]/table/tbody')
    song_list_name_tree = tree.xpath('//h2[contains(@class,"f-ff2")]/text()')
    song_list_name = str(song_list_name_tree[0]) if song_list_name_tree else None

    # 設(shè)置音樂下載的文件夾為歌手名字或歌單名
    folder = './' + artist_name if artist_name else './' + song_list_name

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

    for i, s in enumerate(song_list):
        href = str(s.xpath('./@href')[0])
        song_id = href.split('=')[-1]
        src = out_link + song_id  # 拼接獲取音樂真實(shí)的src資源值
        title = str(s.xpath('./text()')[0])  # 音樂的名字
        filename = title + '.mp3'
        filepath = folder + '/' + filename
        print('開始下載第{}首音樂:{}\n'.format(i + 1, filename))

        try:  # 下載音樂
            #下載歌詞
            #download_lyric(title, song_id)

            data = requests.get(src).content  # 音樂的二進(jìn)制數(shù)據(jù)

            with open(filepath, 'wb') as f:
                f.write(data)
        except Exception as e:
            print(e)

    print('{}首全部歌曲已經(jīng)下載完畢!'.format(len(song_list)))


def download_lyric(song_name, song_id):
    url = 'http://music.163.com/api/song/lyric?id={}&lv=-1&kv=-1&tv=-1'.format(song_id)
    # 請(qǐng)求頭
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
        'Referer': 'https://music.163.com/',
        'Host': 'music.163.com'
        # 'Origin': 'https://music.163.com'
    }
    # 請(qǐng)求頁面的源碼
    res = requests.get(url=url, headers=headers).text
    json_obj = json.loads(res)
    lyric = json_obj['lrc']['lyric']
    reg = re.compile(r'\[.*\]')
    lrc_text = re.sub(reg, '', lyric).strip()

    print(song_name, lrc_text)




if __name__ == '__main__':
    #music_list = 'https://music.163.com/#/playlist?id=2384642500' #歌曲清單
    music_list = 'https://music.163.com/#/artist?id=8325' #歌手排行榜
    # music_list = 'https://music.163.com/#/search/m/?order=hot&cat=全部&limit=435&offset=435&s=梁靜茹' #搜索列表
    download_songs(music_list)

參考


  • 如有疑問容握,歡迎在評(píng)論區(qū)一起討論车柠!
  • 如有不正確的地方脖旱,歡迎指導(dǎo)介蛉!


注:本文首發(fā)于 iHTCboy's blog溶褪,如若轉(zhuǎn)載,請(qǐng)注來源

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吹菱,一起剝皮案震驚了整個(gè)濱河市彭则,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌输瓜,老刑警劉巖芬萍,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異北戏,居然都是意外死亡漫蛔,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門蠕嫁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轧房,“玉大人,你說我怎么就攤上這事迟赃〕д颍” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵酌媒,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我喇辽,道長(zhǎng)雨席,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任抽米,我火速辦了婚禮糙置,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘标捺。我一直安慰自己网持,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布萍倡。 她就那樣靜靜地躺著辟汰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪帖汞。 梳的紋絲不亂的頭發(fā)上翩蘸,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音扶踊,去河邊找鬼郎任。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舶治,可吹牛的內(nèi)容都是我干的车猬。 我是一名探鬼主播尺锚,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼缩麸,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吹散,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤空民,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后界轩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抖甘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年衔彻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了偷办。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柄沮,死狀恐怖废岂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情泪喊,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布哈扮,位于F島的核電站滑肉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏靶庙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一护姆、第九天 我趴在偏房一處隱蔽的房頂上張望掏击。 院中可真熱鬧,春花似錦灯变、人聲如沸捅膘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽愧沟。三九已至,卻和暖如春沐寺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狐援。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國打工究孕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人镶殷。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓微酬,卻偏偏與公主長(zhǎng)得像颤陶,于是被迫代替她去往敵國和親陷遮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容