python爬取網易雲歌單
阿新 • • 發佈:2018-12-16
背景
這學期報了一門海量資料處理,在資料處理前需要爬取一些內容。所以做了一個小練習,爬取網易雲的歌單。其中包括歌單名稱,播放量和url地址。
網易雲還是具有一些反爬措施的,這裡主要說以下幾個方面以及我的應對措施。
- 無法直接訪問 我沒有實踐過直接訪問網易雲音樂會不會被報404,所以這一條本質上不太確定的,我的做法是直接在瀏覽器中通過F12檢視請求頭,在程式碼中將請求頭加入其中以此來模擬我是瀏覽器訪問的,但是後期因為使用了PhantomJS,也就不需要請求頭的,後期的時候請求頭就沒有再用了。
- 動態頁面載入 動態的頁面載入導致正常的頁面爬蟲無法工作,在瀏覽器上看到的很多內容,通過python讀取到html後在內部找不到對應內容。對應的方法是使用PhantomJS。PhantomJS按照我自己的理解,是模擬了一個瀏覽器,這樣子可以最大程度上讓伺服器認為我是普通使用者的瀏覽器,從而防止被反爬。此外上一條中說到使用這個以後不需要再加請求頭也是這個原因,我的身份已經變成了一個瀏覽器,所以也就不需要再使用請求頭來偽裝身份。
- PhantomJS效率過低 PhantomJS畢竟是一個瀏覽器,在速度上有很大劣勢,所以在使用時需要對其進行配置。從直觀上來看,就是關閉瀏覽器的圖片載入功能,開啟瀏覽器快取功能等等,所有的配置都和瀏覽器正常設定差不多,其程式碼如下:
service_args=[]
service_args.append('--load-images=no') ##關閉圖片載入
service_args.append('--disk-cache=yes') ##開啟快取
service_args.append('--ignore-ssl-errors=true') ##忽略https錯誤
- 部分頁面需要滾輪下拉才能顯示更多內容
以下是結果:
程式碼
from selenium import webdriver
import csv
import random
import os
#讀取檔案 若檔案不存在則新建檔案 同時寫入表頭
if os.path.exists('playList.csv'):
csvFile = open('playList.csv', 'a+', newline='', encoding="utf-8")
writer = csv.writer(csvFile)
else:
csvFile = open('playList.csv', 'a+', newline='', encoding="utf-8")
writer = csv.writer(csvFile)
writer.writerow(['標題', '播放數', '連結'])
#配置PhantomJS,提綱爬取速度
service_args=[]
service_args.append('--load-images=no') ##關閉圖片載入
service_args.append('--disk-cache=yes') ##開啟快取
service_args.append('--ignore-ssl-errors=true') ##忽略https錯誤
playUrl = 'https://music.163.com/#/user/home?id=1320157310'
runCnt = 0 #程式執行次數計數
cPlayerList = [] #url列表 噹噹前url不合適時,從內部隨機取出一個繼續爬取
while runCnt < 10000: #爬取兩千條記錄
driver = webdriver.PhantomJS("D:\Python\Python37\Scripts\phantomjs.exe", service_args=service_args)
print(playUrl) #列印當前爬取的url
driver.get(playUrl) #獲取連結
try: #在網頁中若出現錯誤及時捕獲
#-----------------讀取使用者自建歌單-------------------
driver.switch_to.frame('contentFrame')
data = driver.find_element_by_id('cBox').find_elements_by_tag_name('li')
for i in range(len(data)):
nb = data[i].find_element_by_class_name('nb').text
msk = data[i].find_element_by_css_selector('a.msk')
writer.writerow([msk.get_attribute('title'),
nb, msk.get_attribute('href')])
runCnt += 1
print('runCnt:', runCnt)
#-----------------讀取使用者收藏歌單-------------------
data = driver.find_element_by_id('sBox').find_elements_by_tag_name('li')
for i in range(len(data)):
nb = data[i].find_element_by_class_name('nb').text
nb.replace(u'\xa0', u' ');
msk = data[i].find_element_by_css_selector('a.msk')
#UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 2: illegal multibyte sequence
#csvFile = open('playList.csv', 'w', newline='', encoding="utf-8")
writer.writerow([msk.get_attribute('title'),
nb, msk.get_attribute('href')])
runCnt += 1
print('runCnt:', runCnt)
cPlayerList.append(msk.get_attribute('href'))
#從url列表中隨機讀取一個作為下一爬取的url
randIndex = int(random.uniform(0, len(cPlayerList)))
playUrl = cPlayerList[randIndex]
del cPlayerList[randIndex] #列表中取走後需要在列表中將該url刪除
#轉到的頁面是歌單的詳細頁面,以下程式碼負責讀取該頁面中的作者頁面,跳轉到作者頁面以便繼續爬取
driver.get(playUrl)
driver.switch_to.frame('contentFrame')
data = driver.find_element_by_id('m-playlist').find_element_by_class_name('cntc').find_element_by_class_name('name')
playUrl = data.find_element_by_css_selector('a.s-fc7').get_attribute('href')
except:
#若出現錯誤,從url列表中繼續取出一個url
randIndex = int(random.uniform(0, len(cPlayerList)))
playUrl = cPlayerList[randIndex]
del cPlayerList[randIndex]
print('頁面發生異常,取出一個備用url,當前url剩餘:', len(cPlayerList))
driver.get(playUrl)
driver.switch_to.frame('contentFrame')
data = driver.find_element_by_id('m-playlist').find_element_by_class_name('cntc').find_element_by_class_name(
'name')
playUrl = data.find_element_by_css_selector('a.s-fc7').get_attribute('href')
插入連結與圖片
以後希望自己能多寫一些機器學習相關的部落格,現在進入研一也有一個多月了,慢慢的更確立了自己的學習方向。對爬蟲有些興趣但不是主要的學習方向,以後可能除非專案需要,否則不太會用爬蟲去爬一些資料。 立下flag,以後多寫機器學習。