Python爬蟲音頻數據
一:前言
本次爬取的是喜馬拉雅的熱門欄目下全部電臺的每個頻道的信息和頻道中的每個音頻數據的各種信息,然後把爬取的數據保存到mongodb以備後續使用。這次數據量在70萬左右。音頻數據包括音頻下載地址,頻道信息,簡介等等,非常多。
昨天進行了人生中第一次面試,對方是一家人工智能大數據公司,我準備在這大二的暑假去實習,他們就要求有爬取過音頻數據,所以我就來分析一下喜馬拉雅的音頻數據爬下來。目前我還在等待三面中,或者是通知最終面試消息。 (因為能得到一定肯定,不管成功與否都很開心)
二:運行環境
- IDE:Pycharm 2017
- Python3.6
- pymongo 3.4.0
- requests 2.14.2
- lxml 3.7.2
- BeautifulSoup 4.5.3
三:實例分析
1.首先進入這次爬取的主頁面http://www.ximalaya.com/dq/all/ ,可以看到每頁12個頻道,每個頻道下面有很多的音頻,有的頻道中還有很多分頁。抓取計劃:循環84個頁面,對每個頁面解析後抓取每個頻道的名稱,圖片鏈接,頻道鏈接保存到mongodb。
熱門頻道
2.打開開發者模式,分析頁面,很快就可以得到想要的數據的位置。下面的代碼就實現了抓取全部熱門頻道的信息,就可以保存到mongodb中。
start_urls = [‘http://www.ximalaya.com/dq/all/{}‘.format(num) for num in range(1, 85)]
for start_url in start_urls:
html = requests.get(start_url, headers=headers1).text
soup = BeautifulSoup(html, ‘lxml‘)
for item in soup.find_all(class_="albumfaceOutter"):
content = {
‘href‘: item.a[‘href‘],
‘title‘: item.img[‘alt‘],
‘img_url‘: item.img[‘src‘]
}
print(content)
分析頻道
3.下面就是開始獲取每個頻道中的全部音頻數據了,前面通過解析頁面獲取到了美國頻道的鏈接。比如我們進入http://www.ximalaya.com/6565682/album/237771 這個鏈接後分析頁面結構。可以看出每個音頻都有特定的ID,這個ID可以在一個div中的屬性中獲取。使用split()和int()來轉換為單獨的ID。
頻道頁面分析
4.接著點擊一個音頻鏈接,進入開發者模式後刷新頁面然後點擊XHR,再點擊一個json鏈接可以看到這個就包括這個音頻的全部詳細信息。
html = requests.get(url, headers=headers2).text
numlist = etree.HTML(html).xpath(‘//div[@class="personal_body"][email protected]
音頻頁面分析
5.上面只是對一個頻道的主頁面解析全部音頻信息,但是實際上頻道的音頻鏈接是有很多分頁的。
html = requests.get(url, headers=headers2).text
ifanother = etree.HTML(html).xpath(‘//div[@class="pagingBar_wrapper"]/a[last()-1][email protected])
if len(ifanother):
num = ifanother[0]
print(‘本頻道資源存在‘ + num + ‘個頁面‘)
for n in range(1, int(num)):
print(‘開始解析{}個中的第{}個頁面‘.format(num, n))
url2 = url + ‘?page={}‘.format(n)
# 之後就接解析音頻頁函數就行,後面有完整代碼說明
分頁
6.全部代碼
完整代碼地址github.com/rieuse/learnPython
__author__ = ‘布咯咯_rieuse‘
import json
import random
import time
import pymongo
import requests
from bs4 import BeautifulSoup
from lxml import etree
clients = pymongo.MongoClient(‘localhost‘)
db = clients["XiMaLaYa"]
col1 = db["album"]
col2 = db["detaile"]
UA_LIST = [] # 很多User-Agent用來隨機使用可以防ban,顯示不方便不貼出來了
headers1 = {} # 訪問網頁的headers,這裏顯示不方便我就不貼出來了
headers2 = {} # 訪問網頁的headers這裏顯示不方便我就不貼出來了
def get_url():
start_urls = [‘http://www.ximalaya.com/dq/all/{}‘.format(num) for num in range(1, 85)]
for start_url in start_urls:
html = requests.get(start_url, headers=headers1).text
soup = BeautifulSoup(html, ‘lxml‘)
for item in soup.find_all(class_="albumfaceOutter"):
content = {
‘href‘: item.a[‘href‘],
‘title‘: item.img[‘alt‘],
‘img_url‘: item.img[‘src‘]
}
col1.insert(content)
print(‘寫入一個頻道‘ + item.a[‘href‘])
print(content)
another(item.a[‘href‘])
time.sleep(1)
def another(url):
html = requests.get(url, headers=headers2).text
ifanother = etree.HTML(html).xpath(‘//div[@class="pagingBar_wrapper"]/a[last()-1][email protected])
if len(ifanother):
num = ifanother[0]
print(‘本頻道資源存在‘ + num + ‘個頁面‘)
for n in range(1, int(num)):
print(‘開始解析{}個中的第{}個頁面‘.format(num, n))
url2 = url + ‘?page={}‘.format(n)
get_m4a(url2)
get_m4a(url)
def get_m4a(url):
time.sleep(1)
html = requests.get(url, headers=headers2).text
numlist = etree.HTML(html).xpath(‘//div[@class="personal_body"][email protected]_ids‘)[0].split(‘,‘)
for i in numlist:
murl = ‘http://www.ximalaya.com/tracks/{}.json‘.format(i)
html = requests.get(murl, headers=headers1).text
dic = json.loads(html)
col2.insert(dic)
print(murl + ‘中的數據已被成功插入mongodb‘)
if __name__ == ‘__main__‘:
get_url()
7.如果改成異步的形式可以快一點,只需要修改成下面這樣就行了。我試了每分鐘要比普通的多獲取近100條數據。這個源代碼也在github中。
異步
五:總結
這次抓取的數據量在70萬左右,這些數據後續可以進行很多研究,比如播放量排行榜、時間區段排行、頻道音頻數量等等。後續我將繼續學習使用科學計算和繪圖工具來進行數據分析,清洗的工作。
學習過程中遇到什麽問題或者想獲取學習資源的話,歡迎加入學習交流群
626062078,我們一起學Python!
Python爬蟲音頻數據