python爬虫-爬取高逼格音乐网站《落网》

作者: s_nash | 来源:发表于2017-11-10 10:20 被阅读359次

    关于

    落网,一个高逼格的音乐网站,是很多文艺青年经常逛的网站。经常下载落网音乐到本地,一首一首的下载十分的痛苦。最近刚好在学习python爬虫的东西,刚好把落网音乐的爬取当做一个练习项目来实践(IT从业者的好处~)。

    准备

    工具 :python 2.7,PyCharm

    类库:urllib2、BeautifulSoup、time、re、sys

    分析

    要想下载落网的音乐,首先要获取每首音乐的url,通过chrome浏览器的开发者工具(F12)查看网页的源代码可以看到图片的URL,没有音频的URL,如图

    image

    但是,我们发现点击每首歌曲的时候,network都会一个音频的请求,如图

    image

    那么很显然,这个就是我们需要的下载URL地址了。通过分析http://mp3-cdn2.luoo.net/low/luoo/radio924/02.mp3这个地址,我可以知道前面部分http://mp3-cdn2.luoo.net/low/luoo/是固定的地址,后面的radio924/02.mp3中924是每个期刊的期刊号,其中02是每个期刊下面的第几首歌。要想获取同类型期刊(比如rock),URL为http://www.luoo.net/music/rock,首先我们要获取每个期刊的期刊号于期刊URL的对应关系,通过抓取HTML源码来获得,如图

    image.png
    代码如下:
        #获取每个期刊URL与频道的对应关系,存放在一个dict中
        def getReation(self, pageIndex):
            soup = self.getPage(pageIndex, '')
            vols = {}
            pattern = re.compile('[0-9]+')  //正则匹配获取HTML源码中的期刊号
            if not soup:
                return None
            vol_lists = soup.find_all('div', class_='meta')
            for vol in vol_lists:
                vol1 = re.search(pattern, str(vol.a.get_text())).group()
                vols[vol1.strip()] = vol.a['href']
            return vols
    

    然后根据上面的对应关心来获取每首歌的信息,同样存放在一个dict中,以songName为key,以URL为value,如下。

        #获取每首歌的名称和url
        def getSongInfo(self, vols):
            songInfos = {}
            for vol in vols.keys():
                url = vols[vol]
                soup = self.getPage(0, url)
                total = len(soup.find_all('li', class_='track-item'))
                songNames = soup.find_all('a', class_='trackname')
                for i in range(1, total+1):
                    songName = self.delSongName(songNames[i - 1].get_text())
                    if i < 10:  //对前面【1-9】首的URL进行格式化。
                        songURL = self.music_url + 'radio' + str(vol).lstrip('0') + '/0' + str(i) + '.mp3'
                    else:
                        songURL = self.music_url + 'radio' + str(vol).lstrip('0') + '/' + str(i) + '.mp3'
                    songInfos[songName] = songURL
            return songInfos
    

    获取到每首歌的信息后,然后我们就可以正式的进行下载了(哈哈,终于到正题了~),如下

        def downloadSong(self):
            totalPage = self.getTotalPage()  //首先获取该类型期刊的总的页数
            for pageIndex in range(1, int(totalPage)+1):
                vols = self.getReation(pageIndex) //获取每一页的期刊号与URL的对应关系
                songInfos = self.getSongInfo(vols)  //获取歌曲信息name和URL
                for songName, songURL in songInfos.items():
                    time.sleep(5)
                    print('%s 正在下载中。。。' %(songName))
                    try:
                        data = urllib2.urlopen(songURL).read()
                    except urllib2.URLError:
                        print("######链接不存在,继续下载下一首########")
                    with open (('D:\\test\\song\\%s.mp3' %(songName)).decode('utf-8'), 'wb') as f:
                        f.write(data)
    

    总结
    到这边,基本上,对爬取每个类期刊下面的歌曲有了一个整体的思路,大家可以根据这些来实现自己的爬虫额。
    下面给出本人的实现代码,给大家一个参考。

    #!-*- coding: utf-8 -*-
    
    import urllib2,urllib
    from bs4 import BeautifulSoup
    import re
    import time
    import sys
    
    reload(sys)
    sys.setdefaultencoding( "utf-8" )
    
    class DownloadSong(object):
        def __init__(self,base_url):
            self.url = base_url
            self.music_url = 'http://mp3-cdn2.luoo.net/low/luoo/'
            self.pageIndex = 1
            self.headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'
            }
    
        #获取页面的源码
        def getPage(self, index, vol_url):
            if index != 0:
                url = self.url + '?p=' + str(index)
            else:
                url = vol_url
            try:
                request = urllib2.Request(url, headers=self.headers)
                response = urllib2.urlopen(request).read()
                soup = BeautifulSoup(response, 'html.parser')
                return soup
            except urllib2.URLError, e:
                if hasattr(e, 'reason'):
                    print(u'链接失败,失败原因', e.reason)
                    return None
    
        #获取总页面数
        def getTotalPage(self):
            soup = self.getPage(self.pageIndex, '')
            if not soup:
                return None
            totalPage = soup.find_all('a', class_='page')[-1].get_text().strip()
            return totalPage
    
        #处理歌曲的名称
        def delSongName(self, songName):
            return songName.split('.')[1].lstrip().encode('utf-8')
    
        #获取每个期刊URL与频道的对应关系
        def getReation(self, pageIndex):
            soup = self.getPage(pageIndex, '')
            vols = {}
            pattern = re.compile('[0-9]+')
            if not soup:
                return None
            vol_lists = soup.find_all('div', class_='meta')
            for vol in vol_lists:
                vol1 = re.search(pattern, str(vol.a.get_text())).group()
                vols[vol1.strip()] = vol.a['href']
            return vols
    
        #获取每首歌的名称和url
        def getSongInfo(self, vols):
            songInfos = {}
            for vol in vols.keys():
                url = vols[vol]
                soup = self.getPage(0, url)
                total = len(soup.find_all('li', class_='track-item'))
                songNames = soup.find_all('a', class_='trackname')
                for i in range(1, total+1):
                    songName = self.delSongName(songNames[i - 1].get_text())
                    if i < 10:
                        songURL = self.music_url + 'radio' + str(vol).lstrip('0') + '/0' + str(i) + '.mp3'
                    else:
                        songURL = self.music_url + 'radio' + str(vol).lstrip('0') + '/' + str(i) + '.mp3'
                    songInfos[songName] = songURL
            return songInfos
    
        #下载歌曲
        def downloadSong(self):
            totalPage = self.getTotalPage()
            for pageIndex in range(1, int(totalPage)+1):
                vols = self.getReation(pageIndex)
                songInfos = self.getSongInfo(vols)
                for songName, songURL in songInfos.items():
                    time.sleep(5)  //适当的减慢下载速度,不要给人家服务器造成压力。
                    print('%s 正在下载中。。。' %(songName))
                    try:
                        data = urllib2.urlopen(songURL).read()
                    except urllib2.URLError:
                        print("######链接不存在,继续下载下一首########")
                    with open (('D:\\test\\song\\%s.mp3' %(songName)).decode('utf-8'), 'wb') as f:
                        f.write(data)
    
    if __name__ == '__main__':
        url = 'http://www.luoo.net/music/classical'  //传入古典期刊的url
        downloadsong = DownloadSong(url) //生成一个对象
        downloadsong.downloadSong()  //调用downloadSong方法来正式下载额。
    

    结果如下


    image.png
    image.png

    如果对您有点帮助的话,麻烦您给点个赞,谢谢。

    scrapy版本的Python + Scrapy爬取高逼格音乐网站《落网》

    相关文章

      网友评论

        本文标题:python爬虫-爬取高逼格音乐网站《落网》

        本文链接:https://www.haomeiwen.com/subject/ayrvmxtx.html