網(wǎng)易音樂歌詞——分析張學(xué)友108張專輯唱了什么?

簡要概述:

話不多說先上詞云,我們來看下網(wǎng)易云上張學(xué)友從1985-01-01《BTB 3EP張學(xué)友 + 黃凱芹》到 2014-12-23《醒著做夢》一共108張專輯,1300多首歌曲里到底唱了什么!?

先從網(wǎng)易云上獲取張學(xué)友所有歌曲的歌詞化借,然后把所有的歌詞去重后全拼接成一個大文本潜慎,再然后~通過文本切詞將文本切開獲取所有的名詞及動名詞捡多,切分后的結(jié)果如下:

愛情 0.07072471042756841
世界 0.06268317887188746
感覺 0.05650215736324936
眼淚 0.044849511174034074
傷心 0.039332645851527105
思念 0.03834038757061952
世間 0.03682804854767579
故事 0.03475690253214765
眼睛 0.03445409416550336
天空 0.03350860508998348
流淚 0.03312398416346928
夢想 0.03280878370931647
心窩 0.03243319396705214
記憶 0.03158641388911513
風(fēng)雨 0.031456840476264326
星光 0.031069493653815176
笑容 0.030964867927921528
心痛 0.0307011710153588
空虛 0.029434459508895196
春風(fēng) 0.02918087252372948
感情 0.028306639850443988
癡心 0.02801903059970057
深宵 0.027155899335446567
光陰 0.02679152211589159
情人 0.026615621955302014
黑夜 0.026111296684488385
我會 0.025771411677059368
人生 0.02545445923579143
背影 0.02465825420524522

詞云生成用到了Tagul。非常棒的詞云在線生成工具铐炫,你只需要下載一個unicode編碼的字體包垒手,如:arial unicode ms.ttf,接下來只需要將上面列表復(fù)制進(jìn)詞云表單里就可以生成酷炫的詞云了倒信。Tagul官網(wǎng)傳送門:https://wordart.com/gallery

歌詞的獲取和文本切詞科贬,使用的語言是python,主要用到幾個模塊鳖悠,bs4榜掌,requests,jieba乘综,mysqldb 等憎账,這些模塊都可以通過pip install xxx這個指令快速安裝,由于這里只獲取張學(xué)友歌詞所以沒必要用到scrapy太重了卡辰,如果需要爬去全站的可以使用scrapy框架胞皱。

策略&思路:

獲取網(wǎng)易音樂的信息比較不容易邪意,基本上都是動態(tài)加載,反爬機制較完善反砌。如果你是初學(xué)雾鬼,一定在這上面會遇到不少會坑的地方,這里簡單說下爬取思路宴树。經(jīng)供參考

因為只想分析學(xué)友唱了什么策菜,所以就直接在搜索欄搜學(xué)友,點選所有專輯如上圖酒贬,我們看到這樣一串鏈接http://music.163.com/#/artist/album?id=6460做入,看不出是什么?別急

我們點選到第二頁看看變化同衣,我們看到此時的url是http://music.163.com/#/artist/album?id=6460&limit=12&offset=12
第三頁http://music.163.com/#/artist/album?id=6460&limit=12&offset=24

我們分析出其實offset從12變化到了24竟块,有經(jīng)驗的爬友們可以知道limit12其實是每個頁面有12張專輯,所以每翻一頁url的offset+12耐齐,那么我們不用做翻浪秘,看他他總頁數(shù)是9頁那么9*12=108,那么學(xué)友至今108張專輯埠况,真的是牛逼了耸携。
那么我們嘗試將url改成http://music.163.com/#/artist/album?id=6460&limit=108 不需要翻頁,讓頁面直接顯示108張專輯辕翰,ok我們接下來開始requests.get...Beautifulsoup...夺衍。

如果你們真的requests.get...Beautifulsoup...了,那么恭喜你喜命,你成功被耍了沟沙。因為你返回的頁面沒有你要的數(shù)據(jù)。

好壁榕!我們打開chrome抓包矛紫,在密密麻麻的加載項中發(fā)現(xiàn)一個非常熟悉的鏈接,點開發(fā)現(xiàn)他真實request url其實是不帶#號的牌里,說明之前那個url是假的



ok再次requests.get...Beautifulsoup

我們要的數(shù)據(jù)也取到了颊咬,然后獲取該專輯href,然后做鏈接拼接再進(jìn)入專輯詳情頁牡辽。這里詳情頁獲取同上需要進(jìn)入抓包分析具體鏈接


爬爬爬~ 都爬了~ 經(jīng)過之地寸草不生~

在爬去歌單的時候需要獲取后面的歌曲id如下圖

然后拼接歌詞api喳篇,api是由百度提供~我們只需要將歌曲id放入去拼接出url,再次requests即可獲取詳細(xì)歌詞
http://music.163.com/api/song/lyric?os=pc&id= str(song_id) &lv=-1&kv=-1&tv=-1

注意事項:

這里注意爬取的時候頻繁返回503态辛,經(jīng)常會報錯或者漏爬麸澜,短時間不能再次爬取,時間大概在半小時因妙,所以大家可以類似這樣的代碼去判斷爬取失敗的循環(huán)

if response.status_code <> 200:
    requests_error_list.append(response.url)
    time.sleep(300)

有了爬去失敗列表那么在最后將這些url再拿出來再次爬取痰憎,同樣先判斷狀態(tài)是否200票髓,然后判斷url后綴,類似album?id=19008這樣的則是專輯名url铣耘,song?id=187449則為歌曲url
參考代碼:

if requests_error_list:
    for url in requests_error_list:
        if 'album?id=' in url:
            requests_album_url()
        if 'song?id=' in url:
            requests_song_url()
        response.status_code <> 200:
        requests_error_list.append(url)
        time.sleep(300)
爬蟲代碼:
conn = MySQLdb.connect(host="localhost",
                       user="root",
                       passwd="root",
                       db="webspider",
                       charset="utf8",
                       use_unicode=True)
cursor = conn.cursor()
cursor2 = conn.cursor()

def ua_random():
    headers = {
        "User-Agent": UserAgent().Chrome,
        "Connection": "keep-alive",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.8",
        "Referer": "http: // music.163.com /"
    }
    return headers

url = 'http://music.163.com/artist/album?id=6460&limit=108'

response = requests.get(url, headers=ua_random())
print(response.status_code)
soup = BeautifulSoup(response.content, 'lxml')
album_href_taglist = soup.select('a.tit.s-fc0')

album_href_list = [_.get('href') for _ in album_href_taglist]
album_id_list = [_.split('=')[1].strip() for _ in album_href_list]
print(album_id_list)
for album_id in album_id_list:
    url2 = ''.join(['http://music.163.com/album?id=', album_id])
    response2 = requests.get(url2, headers=ua_random())
    soup2 = BeautifulSoup(response2.content, 'lxml')
    # print(soup2)
    song_taglist = soup2.select('ul.f-hide a')
    # print(song_taglist)
    song_href_list = [_.get('href') for _ in song_taglist]
    song_id_list = [_.split('=')[1].strip() for _ in song_href_list]
    # print(song_id_list)

    album_id = album_id.strip()
    try:
        album_name = soup2.select_one('h2.f-ff2').get_text().strip()
        album_issue_date = soup2.select('p.intr')[1].get_text().split(':')[1].strip()
        try:
            issue_company_name = soup2.select('p.intr')[2].get_text().split(':')[1].strip()
        except IndexError:
            issue_company_name = None
    except:
        album_name = None
        album_issue_date = None
        print(response2.status_code, response2.url)
        continue

    insert_sql = """INSERT INTO album_info(album_id ,album_name,album_issue_date,issue_company_name)
                    VALUES (%s, %s, %s, %s)
    """
    print(album_id,
          album_name,
          album_issue_date,
          issue_company_name)
    cursor.execute(insert_sql, (album_id,
                                album_name,
                                album_issue_date,
                                issue_company_name))

    song_info_temp = soup2.textarea.get_text()
    song_info = json.loads(song_info_temp)

    for v in song_info:
        song_id = v['id']
        song_name = v['name']
        singer = ','.join([_['name'] for _ in v['artists']])
        song_time = None
        album_id = album_id.strip()

        url3 = ''.join(['http://music.163.com/api/song/lyric?os=pc&id=',
                        str(song_id),
                        '&lv=-1&kv=-1&tv=-1'])

        response3 = requests.get(url3, headers=ua_random())
        # time.sleep(1)
        soup3 = BeautifulSoup(response3.content, 'lxml')
        # print(soup3.get_text())
        try:
            lrc_temp = json.loads(soup3.get_text())['lrc']['lyric']
            lyric = re.sub(r"\[(.*)\]", '', lrc_temp)
        except KeyError:
            lyric = '無歌詞'

        except json.decoder.JSONDecodeError:
            lyric = None
            print(response3.status_code, response3.url)

        insert_sql = """INSERT INTO song_info(song_id,song_name,song_time,singer,lyric,album_id)
                        VALUES (%s, %s, %s, %s, %s, %s)
        """
        cursor2.execute(insert_sql, (song_id,
                                     song_name,
                                     song_time,
                                     singer,
                                     lyric,
                                     album_id))

conn.commit()
conn.close()
jieba分詞代碼:
conn = MySQLdb.connect(host="localhost",
                       user="root",
                       passwd="root",
                       db="webspider",
                       charset="utf8",
                       use_unicode=True)

sql = '''
SELECT * from webspider.album_info as a
left join webspider.song_info as b on a.album_id = b.album_id
where b.lyric IS NOT NULL AND b.lyric <> '無歌詞'

'''
df = pandas.read_sql(sql, con=conn, )
# print(df.head(10))
t_list = df.lyric
all_union_text = ';'.join(t_list).replace('作曲 :', '').replace('作詞 :', '')
text = ','.join(set(','.join(set(all_union_text.split('\n'))).split()))

# seg_list = jieba.cut(all_union_text,cut_all=True)
# print(' '.join(seg_list))

keywords = jieba.analyse.extract_tags(text, topK=20, withWeight=True, allowPOS=('n', 'nv'))
for i in keywords:
    print(i[0], i[1])
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洽沟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蜗细,更是在濱河造成了極大的恐慌裆操,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炉媒,死亡現(xiàn)場離奇詭異踪区,居然都是意外死亡,警方通過查閱死者的電腦和手機吊骤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門缎岗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人白粉,你說我怎么就攤上這事传泊。” “怎么了鸭巴?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵眷细,是天一觀的道長。 經(jīng)常有香客問我鹃祖,道長溪椎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任恬口,我火速辦了婚禮校读,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘楷兽。我一直安慰自己地熄,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布芯杀。 她就那樣靜靜地躺著,像睡著了一般雅潭。 火紅的嫁衣襯著肌膚如雪揭厚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天扶供,我揣著相機與錄音筛圆,去河邊找鬼。 笑死椿浓,一個胖子當(dāng)著我的面吹牛太援,可吹牛的內(nèi)容都是我干的闽晦。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼提岔,長吁一口氣:“原來是場噩夢啊……” “哼仙蛉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碱蒙,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤荠瘪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后赛惩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哀墓,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年喷兼,在試婚紗的時候發(fā)現(xiàn)自己被綠了篮绰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡季惯,死狀恐怖阶牍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情星瘾,我是刑警寧澤走孽,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站琳状,受9級特大地震影響磕瓷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜念逞,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一困食、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧翎承,春花似錦硕盹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至甸各,卻和暖如春垛贤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背趣倾。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工聘惦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人儒恋。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓善绎,卻偏偏與公主長得像黔漂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子禀酱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

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