Python爬取喜馬拉雅FM音頻

前前言

喜馬拉雅已經(jīng)更換標(biāo)簽,我重新更新了下代碼,思路還是如此,需要的可以掃一下文末公眾號(hào)二維碼(本人會(huì)在上面發(fā)表爬蟲以及java的文章還有送書等資源福利哦),也可以直接搜索公眾號(hào)“ 猿獅的單身日?!保昧藦V告結(jié)束...

前言

之前寫過爬取圖片的一篇文章,這回來看看如何爬取音頻。圖片,音頻,視頻這類都可以通過二進(jìn)制方式保存到本地下載下來。
爬取圖片文章的鏈接:
python爬取圖片并以二進(jìn)制方式保存到本地

目標(biāo)

本次我們爬取的目標(biāo)是--喜馬拉雅FM


這里寫圖片描述

喜馬拉雅FM有數(shù)不計(jì)的音頻,這些音頻都有自己的分類,所以進(jìn)一步給自己拋出一個(gè)需求,爬取喜馬拉雅所有分類的音頻

接下來我們來分析這些分類,找到所有分類 https://www.ximalaya.com/category/

這里寫圖片描述

我們可以看到這里包括了大量的分類,那么我們找一個(gè)分類來看看其內(nèi)部是怎樣的

這里寫圖片描述

這里我們可以看到文學(xué)類下面的諸多FM節(jié)目,那么點(diǎn)開節(jié)目,有的需要充值,有的免費(fèi),還有很多頁這樣的節(jié)目

這里寫圖片描述

繼續(xù)跟進(jìn),可以看到,我們需要爬取的音頻列表了!
好了,所以現(xiàn)在目標(biāo)已經(jīng)清晰起來了:找到所有分類 -> 對(duì)每一個(gè)分類,獲取其中所有頁的FM節(jié)目->對(duì)每一個(gè)FM節(jié)目,爬取其下列表里的所有免費(fèi)的音頻


開始動(dòng)刀

第一步

代碼如下:

category_Url = 'https://www.ximalaya.com/category/'
base_url = 'https://www.ximalaya.com'
base_api = 'https://www.ximalaya.com/revision/play/tracks?trackIds='
header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'
}
client = pymongo.MongoClient(host='localhost', port=27017)
db = client['ximalaya']

def getUrl():
    r = requests.get(category_Url, headers=header)
    html = r.text
    result = re.findall(r'<a class="e-2880429693 item separator".*?href="(.*?)">(.*?)</a>', html, re.S)
    url_list = []
    for i in result:
        # 以一個(gè)分類為例  - - 有聲書中的文學(xué)類,若沒有break 則可獲取全部分類
        second_url = base_url + i[0]
        url_list.append(second_url)
        # 獲取該分類中全部的頁數(shù)
        getMorePage(second_url)
        print second_url
        break

分析每個(gè)分類的標(biāo)簽,獲取網(wǎng)頁源碼中的所有分類,這里的category_Url是上面提到的所有分類得界面的URL

還定義一些要用到的基本的,比如請求頭、連接MongoDB等,在這里添加了break,是因?yàn)橐纛l數(shù)過多,所以以有聲書為例


第二步

def getMorePage(url):
    r = requests.get(url, headers=header)
    m_list_html = r.text
    pageNum = re.findall(r'(\d+)</span></a></li><li class="e-3793817119 page-next page-item">', m_list_html,re.S)
    pageNum = int(pageNum[0])
    # 循環(huán)獲取每一頁,這里暫時(shí)獲取第一頁
    for i in range(1, pageNum + 1):
        if i == 1:
            page_url = url
            # 獲取頁中的30個(gè)FM
            getMusicList(page_url, i)
        else:
            page_url = url + 'p{}/'.format(i)
            getMusicList(page_url, i)
        #爬取一頁
        break

進(jìn)入一個(gè)分類后,可以看到很多頁的FM節(jié)目,所以應(yīng)該想辦法循環(huán)獲取頁面的內(nèi)容,這里我們發(fā)現(xiàn)頁面數(shù)在網(wǎng)頁源碼中存在,通過正則我們將其取出,然后循環(huán)

這里我們注意一下其頁面的url :
https://www.ximalaya.com/youshengshu/wenxue/p2/
后面的p2對(duì)應(yīng)頁數(shù),而第一頁沒有p,所以需要判斷,這里也同樣以第一頁為例


第三步

def getMusicList(url, page):
    r = requests.get(url, headers=header)
    m_list_html = r.text
    result = re.findall(
        r'<a class="e-1889510108.*?href="(.*?)"><img.*?src="(.*?)".*?alt="(.*?)".*?/>.*?"e-1889510108 icon-earphone xuicon xuicon-erji"></i>(.*?)</span>.*?"e-2896848410 album-author".*?title="(.*?)">',
        m_list_html, re.S)
    info = []
    # 獲取該page中每一個(gè)FM的數(shù)據(jù)信息,可以存入MongoDB
    for i in result:
        FM_info = {}
        #每個(gè)節(jié)目的url
        FM_url = base_url + i[0] 
        FM_info['url'] = FM_url
        FM_info['picture'] = i[1]
        FM_info['name'] = i[2]
        FM_info['playback'] = i[3]
        FM_info['author'] = i[4]
        info.append(FM_info)
        # 獲取該FM中的音頻信息
        # os.mkdir('D:\\Python\\PycharmProject\\Enhance\\xmly_fm\\{}'.format(FM_info['name']))
        get_FM_music(FM_url)
        # 先獲取一個(gè)FM

    # for j in info:
    #     print j
    test = db['page' + str(page)]
    test.insert(info)

以每頁的url為參數(shù)傳入getMusicList()獲取每一頁中的30個(gè)FM節(jié)目信息,可以將每個(gè)節(jié)目的信息存入到MongoDB中;然后是獲取每個(gè)節(jié)目中的音頻


第四步

def get_FM_music(fm_url):
    print fm_url
    r = requests.get(fm_url, headers=header)
    FM_music_html = r.text
    track_list = re.findall(r'<div class="e-2304105070 text"><a.*?title="(.*?)".*?href="(.*?)">.*?</a>', FM_music_html,re.S)
    detail_info = []
    # 爬取一個(gè)FM下的每個(gè)音頻
    j = 1
    for i in track_list:
        detail = {}
        # 獲取爬取音頻所需的trackIds
        id = str(i[1]).split('/')[3]
        detail['title'] = i[0]
        detail['detail_url'] = base_url + i[1]
        detail_info.append(detail)
        # api中的數(shù)據(jù)信息
        get_detailFM_api(id)
        print u'已獲取第' + str(j) + u'個(gè)音頻'
        j += 1
    print detail['title']+u',該音頻爬取完畢'
    time.sleep(2+random.randint(1,10))

獲取每個(gè)音頻對(duì)應(yīng)的url,這里需要注意,自我們點(diǎn)擊一個(gè)音頻的時(shí)候

這里寫圖片描述

進(jìn)入到以下界面

這里寫圖片描述

我們既然要獲取音頻,那么不妨打開開發(fā)者工具,再點(diǎn)擊播放音頻試試
結(jié)果我們發(fā)現(xiàn),點(diǎn)擊播放按鈕,發(fā)送了一個(gè)請求:


這里寫圖片描述

https://www.ximalaya.com/revision/play/tracks?trackIds=93433726
注意trackIds就是當(dāng)前音頻url的最后一部分:
https://www.ximalaya.com/youshengshu/11377428/93433726

同時(shí)我們可以看到我們所需的音頻源就在這里:


這里寫圖片描述

這里寫圖片描述

所以我們可以通過獲取頁面url的最后一部分,構(gòu)建一個(gè)請求,發(fā)送后就可以獲取json數(shù)據(jù),從而獲得音頻源的url


第五步

def get_detailFM_api(id):
    api = base_api + id
    print api
    r = requests.get(api, headers=header)
    result = r.json()
    src = result['data']['tracksForAudioPlay'][0]
    if src['src']:
        print u'試聽'
        r = requests.get(src['src'], headers=header)
        try:
            f = open('D:\\Python\\PycharmProject\\Enhance\\xmly_fm\\{}.m4a'.format(src['trackName']),'wb')
        except:
            print u'已存在'
            pass
        f.write(r.content)
        f.close
        print u'保存完畢...'
    else:
        print u'需要收費(fèi)'
        pass

通過訪問音頻源,以r.content將音頻保存到本地

這里寫圖片描述

這里保存的時(shí)候還需改進(jìn),希望做到對(duì)每個(gè)節(jié)目新建一個(gè)文件夾,將該節(jié)目的音頻存入對(duì)應(yīng)的文件夾中

最后,程序從這里開始運(yùn)行

if __name__ == '__main__':
    getUrl()

有疑問或更好的方法的話,歡迎交流!

下一篇應(yīng)該是爬取網(wǎng)易云的,或者是爬取視頻;最近也是忙著期末的考試,我也算是碰見了最佩服的老師...(考試時(shí)看我們做的試卷,唉,急的直接說答案了??!...)

完整代碼可以在我的GitHub上下載~
https://github.com/joelYing/XimalayaFM


print('微信公眾號(hào)搜索 "猿獅的單身日常" ,Java技術(shù)升級(jí)、蟲師修煉,我們 不見不散!')
print('也可以掃下方二維碼哦~')
猿獅的單身日常
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容