如何用爬蟲獲取網易雲音樂歌單中的歌曲?

用firebug抓包發現訪問http://music.163.com/playlist?id=317113395時返回的內容裡面不包括歌單內歌曲的名字,如下圖所示:

那麼歌名是通過何種方式傳遞給瀏覽器的?用python爬蟲如何獲取歌名呢,謝謝了!


spider163已更新v2.0!
公眾號文章推介:非重磅 | 網易雲音樂爬蟲Spider163更新v2.0
項目源碼及簡介:Chengyumeng/spider163

—————————————————————————————————

瀉藥,以我抓取了307835首網易雲音樂的歌單歌曲的經驗,講一下這個問題。

喜歡用Github的可以直接看我的項目源碼,代碼簡單、具體使用方法和資料庫細節介紹的很全面:

Chengyumeng/spider163

我使用的技術棧是Python + MySQL,資料庫相關的配置可在spider163.conf中配置。

我使用的策略是,通過熱門歌單列表抓取全部歌單名字,熱門歌單URL為:

網易雲音樂

抓下這些熱門URL,持久化到資料庫中,然後繼續通過存儲的歌單URL,繼續抓取歌單裡面的歌曲URL,歌曲的URL格式為:

網易雲音樂

然後下一步,就是針對網易雲音樂的歌曲頁面做信息採集,你可以抓的數據有歌曲的詞曲作者、歌詞、評論等信息,我抓取的數據為歌曲熱評和評論總數。

基於此,可以建立這樣的抓取模型:

歌單列表 -&> 歌單 -&> 歌曲

------------------------分割線是這麼畫嗎?-----------------------------

相關源碼見Github:Chengyumeng/spider163

相關操作:

抓取熱門歌單

$ python playlist.py 1 10
$ # 抓取熱門歌單前十頁的歌單名字和鏈接
$ python playlist.py 粵語 1 42
$ # 抓取全部粵語歌單

抓取歌單內歌曲

$ python music.py playlist 376259016
$ # 抓取編號為 376259016 的歌單
$ python music.py database
$ # 抓取存儲的熱門歌單裡面的歌曲,批量抓取

抓取歌曲評論

$ python comment.py
$ # 自動抓取已存儲歌曲,並保持去重複

TODO

  • 增加抓取歌單頁面個性推薦歌單
  • 增加抓取排行榜
  • 嚴格去重複 ??
  • 優化代碼結構,冗餘代碼過多

BUG

  • 若干歌單無法抓取,待重現定位
  • ...

雖然我沒有使用分散式,但是單線程的效率已經相當不錯,這是MySQL的讀寫圖:

基本上可以保證平均一小時1萬首音樂的抓取。

我的抓取數據:

  • 8600張熱門歌單
  • 307835首歌曲
  • 1410482條評論

歡迎大家使用我的代碼,並進一步做數據挖掘。


您可以關注我的技術分享微信公眾號:程天寫代碼。交流Python、Go、高可用、雲計算等方面學習心得。

本文相關微信文章:我用Python抓取了1008328條網易雲音樂熱評!

相關回答:網易雲音樂評論最多的歌曲有哪些? - 知乎


恩,看了 @路人甲 的回答,我又想了想java8,雖然答非所問用的是java,但是這次java沒得黑,抖個機靈,丑了點,但是的確夠短,哈哈(逃

使用jsoup,鏈接地址也是 http://music.163.com/playlist?id=317113395

java 代碼:


public static void main(String[] args) throws Exception {
Jsoup.connect("http://music.163.com/playlist?id=317113395")
.header("Referer", "http://music.163.com/")
.header("Host", "music.163.com").get().select("ul[class=f-hide] a")
.stream().map(w-&> w.text() + "--&>" + w.attr("href"))
.forEach(System.out::println);
}

效果:


大兄弟,你抓包沒抓對啊!

這兩個url雖然長得像,但僅僅是長得像噢!

http://music.163.com/playlist?id=317113395
http://music.163.com/#/playlist?id=317113395

真正有歌曲信息的是上面那個url,在上圖中很明顯的!既然知道了那我們就直接來抓取吧!只是一個簡單的模擬get請求噢!

只需要你知道這個歌單的ID,我們以題主的為例,抓取結果:

代碼示意,喏:

#encoding=utf8
import requests
from bs4 import BeautifulSoup

headers = {
"Referer":"http://music.163.com/",
"Host":"music.163.com",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
}

play_url = "http://music.163.com/playlist?id=317113395"

s = requests.session()
s = BeautifulSoup(s.get(play_url,headers = headers).content)
main = s.find("ul",{"class":"f-hide"})

for music in main.find_all("a"):
print("{} : {}".format(music.text,music["href"]))


網易雲音樂常用API淺析
GitHub - darknessomi/musicbox: 網易雲音樂命令行版本
Python抓取網頁雲音樂指定歌手的歌曲和評論數量


試試phantomjs解析js渲染的網頁

def getPageByUrl(self,url):
driver = webdriver.PhantomJS()
driver.get(url)
driver.switch_to.frame(driver.find_element_by_xpath("//iframe"))
content = driver.page_source
return content


之前用scrapy寫過一個網易雲音樂爬蟲,抓取全站所有音樂數據。實現起來比較簡單,大致流程如下:

  • 從歌手列表抓取全部歌手;
  • 有全部歌手抓取到全部專輯;
  • 抓取全部專輯的所有音樂地址;
  • 分析AJAX提取熱評信息;
  • 保存資料庫;

源碼地址:github

使用Python3 + Scrapy + Mongodb,運行:

$ scrapy crawl music

抓取效果:

喜歡不妨star鼓勵。


網易雲音樂好多頁面都是js動態生成的,如果分析網路包的話需要分析paramsencSecKey如何生成(或直接套用),個人感覺還挺麻煩的。

建議使用selenium庫,然後調用PhantomJS.exe把頁面載入出來然後再print出來page_source,自然就有頁面的DOM Tree裡邊的內容了。


第一次寫java爬蟲,耗時三天,從網易雲音樂官網,通過歌單分類——歌單列表——歌曲列表,逐級爬取,最終獲得全部歌曲;

關於ip封鎖的問題: 因為沒有代理池,網上的免費代理又太慢。因為我用的校園網,所以我想出一個妙招,通過cmd命令自動更改註冊表mac地址並重新連接,校園網的ip就變了。於是可以高速盡情爬取。想用的同學需要自行查詢如何通過cmd命令更改你們電腦系統的mac地址。

多線程抓取,剛開始速度在2000--3000/分鐘,但是後來估計每個歌單中有大量重複歌曲,速度就降到了400條左右,爬到大概40W數據的時候我懶得爬了。

過程中遇到一個讓我哭笑不得的問題就是:網易雲的頁面的源代碼並不是瀏覽器url(https://music.163.com/#/discover/playlist)那個的,而是它又重新請求了一次(https://music.163.com/discover/playlist) 因為這個小問題我困惑了好久;

另外就是在獲得歌曲評論數的時候,它的請求參數是加密的,但是這個參數在評論列表第一頁是通用的,所以如果只抓評論數量,而不需要抓所有評論的話,可以直接把這個參數拿過來用;

並沒有對代碼進行分層架構,基本上是 能用不能看(慘不忍睹);
有暫停並儲存抓取進度功能;
運行時ConcurrentHashMap去重

最後放上github地址:GuoYankai1996/NetEase-Cloud-Music


抓取網易雲音樂評論內容代碼在此netease-music-spider is a sipder that you can find beautiful girlfiend or handsome boyfriend.

Source Code Structure

  • spider_start.py
  • comment.py
  • user.py
  • music_mysql.py
  • create.sql

Usage method

  1. Use create.sql to create sql database.
  2. Change musci_mysql.py database username and password.
  3. Add your favorite song ID to the songs_name_data list.
  4. Run spider_start.py,and wait a few minutes.
  5. Open the mysql database,then through the search method to find user who favorite songs is the same as you.

License

LzayWorm

Github:wenhaoliang/netease-music-spider


wenhaoliang/netease-music-spider

爬取網易雲音樂評論,

這裡我上傳了一個github倉庫,

裡面有我的爬取全過程,

代碼有很全的注釋說明,

使用步驟也寫的很詳細,

已經獲得了50個star了,

各位可以去github一看,

記得給個star啊!


第一次修改於2017年5月28日10:06:18

聽取了評論區#返回框架源代碼的建議,修改此答案。

只能抓到歌曲和歌曲id完全符合答主的要求,但是 評論什麼的都是js載入的,就抓不到了

上面也有人把帶吧貼出來了,用了beautifulsoup第三方模塊

我給出一個直接用正則的把,python3.6直接運行就行,不用第三方庫

# -*- coding: utf-8 -*-
from urllib import request
import re

url = "http://music.163.com/discover/toplist?id=3778678"
html = request.urlopen(url).read().decode("utf-8")
pa = re.compile("&.+?&<.a&>")
dataList = pa.findall(html)

num = 1
for data in dataList:
print(str(num) + " " +data)
num += 1

-------------------------------------我是分割線------------------------------------------------

樓上的一群人沒有答道關鍵點,我看了半天也沒有看懂也說什麼(也許我智商有限,恩?)

網易雲用了框架frame,所以你右鍵查看源代碼的時候,有兩個選擇,選擇框架源代碼就可以看到你想要的內容了。


解決辦法:

利用技術 seleium+PhantomJS 也可以用seleium+FireFox

網易雲採取了框架,所以必須要driver.switch_to.frame(driver.find_element_by_name("contentFrame"))

//加上這一句,就可以返回框架的源代碼了

暫時只想到了模擬真實瀏覽器的行為。嘗試解析post數據,發覺有兩個js加密

試著查看了js怎麼加密的,發覺寫的亂七八操的,完全不是給人看的,最終放棄了


爬取網易雲,薛之謙熱門30首歌曲的熱門評論 。

思路是先爬到連接,然後打開連接爬評論。

具體代碼如下:

python3.6 源碼放在了github上 wenbochang888/music_comment 歡迎fork
# -*- coding: utf-8 -*-
from selenium import webdriver
from bs4 import BeautifulSoup
import re

def comment(url):
driver = webdriver.PhantomJS()
driver.get(url)
driver.switch_to.frame(driver.find_element_by_name("contentFrame"))
html = driver.page_source
pa = re.compile("&<.a&>.{0,1}[u4e00-u9fa5].+?&<.div&>")
dataList = pa.findall(html)

dataList = str(dataList)
dataList = re.sub("nbsp;","", dataList)
dataList = re.sub("&","",dataList)
dataList = re.sub("&:","---", dataList)
dataList = re.sub("&", "",dataList)
dataList = re.sub("", "", "", dataList)
dataList = re.sub("&", "", dataList)
dataList = re.sub("&", "", dataList)
dataList = dataList.split("---")

try:
for x in range(1,15):
print(str(x)+": "+dataList[x] + "
")
except Exception as e:
print("出問題了 不過不用擔心")

# 同樣可以使用陳奕迅 http://music.163.com/#/artist?id=2116 等一波人的
# 薛之謙的熱門歌曲
url = "http://music.163.com/#/artist?id=5781"
driver = webdriver.PhantomJS()
driver.get(url)
driver.switch_to.frame(driver.find_element_by_name("contentFrame"))
html = driver.page_source

bsObj = BeautifulSoup(html, "html.parser")
dataList = bsObj.findAll(name = "a", attrs = {"href":re.compile(r"/song.id=d{1,10}")})
for data in dataList:
print(data.string + " http://music.163.com/#"+data.attrs["href"] + "
")
comment("http://music.163.com/#"+data.attrs["href"])


看了下回答,發現都是用python代碼的方式抓取。

於是,我花了2分鐘用爬山虎採集器抓去了下。

發現一個好玩的事情:現在網頁的歌曲列表數據竟然做了混淆。

用爬山虎採集器,輸入網址,下一步,自動提取數據。結果如下:

WTF!!!這是什麼鬼???

在去仔細檢查了下源碼發現在歌名中間插了一個隱藏的DIV。。。

這防採集技術也虧得網易程序員想的出來。。。

在爬山虎中很容易搞定。直接點擊欄位,修改取值屬性Text類型,搞定啦!結果如下:

最後

採集花了2分鐘,寫這個回答卻用了10分鐘。


https://github.com/ZWkang/spider/tree/master/網易
貼一個以前做的小東西
(Ps:有的東西已經部分失效


我也在爬蟲這個網易雲音樂列表,因為是初學爬蟲,有些地方爬下來看不太懂,不知道怎麼處理那些爬下來的數據。望大神給出指示啊!!!!!!!!!!!

代碼:代碼還沒有寫完,結果上找到我想要的內容是一個list不,不知道是什麼原因

# -*- coding: cp936 -*-
import requests
from bs4 import BeautifulSoup
r = requests.get(』http://music.163.com/#/discover/toplist『)
html = r.content
#print r.text
#print "------------------------------------------"
soup = BeautifulSoup(html,"html.parser") #html.parser是解析器
music_list = []
div_people_list = soup.find("table", attrs={"class": "m-table m-table-rank"})
print div_people_list

結果:結果太長,沒有列完全,只列了我需要的部分
&{list beg..end as y} //這裡面是我想要的內容
{var x=xlist[y]}
&

{if y<3}
&
這裡有寫好的:
網易雲音樂歌單採集爬蟲


推薦閱讀:

爬蟲怎麼解決封IP?
python爬蟲如何斷點繼續抓取?
python教程看完了,還是不會編程?
Python有哪些常見的、好用的爬蟲框架?
如何去尋找網路爬蟲的需求?

TAG:Python | 爬蟲計算機網路 | 網易雲音樂 |