共計(jì) 5641 個(gè)字符,預(yù)計(jì)需要花費(fèi) 15 分鐘才能閱讀完成。
自動(dòng)寫代碼機(jī)器人,免費(fèi)開通
這期內(nèi)容當(dāng)中丸趣 TV 小編將會(huì)給大家?guī)?lái)有關(guān)如何用 Python 爬取網(wǎng)易云音樂輯的圖片及專輯名和專輯出版時(shí)間,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
一、前言
前文說(shuō)過我的設(shè)計(jì)師小伙伴的設(shè)計(jì)需求,他想做一個(gè)披頭士樂隊(duì)歷年專輯的瀑布圖。
通過搜索,發(fā)現(xiàn)網(wǎng)易云音樂上有比較全的歷年專輯信息加配圖,圖片質(zhì)量還可以,雖然有大有小。
我的例子怎么都是爬取圖片?(誰(shuí)讓你總是跟設(shè)計(jì)師小伙伴一起玩耍。。。)看來(lái)圖片對(duì)于設(shè)計(jì)師來(lái)說(shuō)還是有著很深的情節(jié),那就看他用這些圖片能做出什么樣的作品啦,期待一下,后續(xù)會(huì)展示一下他的作品。
其實(shí)爬取網(wǎng)易云音樂跟之前爬取的網(wǎng)站稍稍有點(diǎn)不同,當(dāng)然,爬蟲寫的多了就覺得套路都是固定的,見招拆招而已。
二、運(yùn)行環(huán)境
我的運(yùn)行環(huán)境如下:
系統(tǒng)版本
Windows10。
Python 版本
Python3.5,推薦使用 Anaconda 這個(gè)科學(xué)計(jì)算版本,主要是因?yàn)樗詭б粋€(gè)包管理工具,可以解決有些包安裝錯(cuò)誤的問題。去 Anaconda 官網(wǎng),選擇 Python3.5 版本,然后下載安裝。
IDE
我使用的是 PyCharm,是專門為 Python 開發(fā)的 IDE。
三、實(shí)戰(zhàn)
上面提到過,網(wǎng)易云音樂的網(wǎng)頁(yè)跟普通的網(wǎng)頁(yè)相比主要有兩點(diǎn)不同:
網(wǎng)頁(yè)是 js 動(dòng)態(tài)加載的
使用了 iframe 框架
所以,首先,網(wǎng)頁(yè)請(qǐng)求不能使用 requests 庫(kù),需要使用 Selenium + PhatomJS。其次,使用 Selenium + PhatomJS 后,還需要針對(duì) iframe 做特定處理。
廢話不多說(shuō),看實(shí)際操作步驟:
首先打開網(wǎng)頁(yè) http://music.163.com
然后看到如下頁(yè)面,選擇紅框中的“所有專輯”,點(diǎn)擊。
我們需要的就是所有專輯的圖片、專輯名和專輯出版時(shí)間。看到這就可以構(gòu)想一下爬蟲的爬取邏輯了。定位到該頁(yè)面,然后獲取頁(yè)碼,然后挨個(gè)請(qǐng)求頁(yè)面來(lái)爬取頁(yè)面中的內(nèi)容。
點(diǎn)擊一下翻頁(yè)按鈕看看 url 有沒有什么規(guī)律。
點(diǎn)擊第二頁(yè)后,看到上面的地址欄!??!看到這個(gè)地址欄我都懶得翻頁(yè)了。。。
limit 參數(shù)是限制一個(gè)頁(yè)面加載專輯的個(gè)數(shù)
offset 參數(shù)是前面過濾多少個(gè)專輯,現(xiàn)在是一頁(yè) 12 個(gè)專輯,所以第二頁(yè)是 offset=12,第三頁(yè) offset=24,以此類推。。。
一共 9 頁(yè),一頁(yè) 12 個(gè),也不到 120 個(gè)。So… … 改一下 url 就不用翻頁(yè)了?。?/p>
limit 參數(shù)等于 120,offset 參數(shù) 等于 0,就搞定了!輸入下面的 url,看看是不是所有的專輯都加載出來(lái)了。
http://music.163.com/#/artist/album?id=101988 limit=120 offset=0
下面就開始爬蟲代碼了。
這里我們會(huì)用到上一篇博文中寫好的幾個(gè)工具方法:
def save_img(self, url, file_name): ## 保存圖片
print(開始請(qǐng)求圖片地址,過程會(huì)有點(diǎn)長(zhǎng)...)
img = self.request(url)
print(開始保存圖片)
f = open(file_name, ab)
f.write(img.content)
print(file_name, 圖片保存成功!)
f.close()
def request(self, url): # 封裝的 requests 請(qǐng)求
r = requests.get(url) # 像目標(biāo) url 地址發(fā)送 get 請(qǐng)求,返回一個(gè) response 對(duì)象。有沒有 headers 參數(shù)都可以。 return r
def mkdir(self, path): ## 這個(gè)函數(shù)創(chuàng)建文件夾
path = path.strip()
isExists = os.path.exists(path)
if not isExists:
print(創(chuàng)建名字叫做 , path, 的文件夾)
os.makedirs(path)
print(創(chuàng)建成功!)
return True
else:
print(path, 文件夾已經(jīng)存在了,不再創(chuàng)建)
return False
def get_files(self, path): # 獲取文件夾中的文件名稱列表
pic_names = os.listdir(path)
return pic_names
OK, 開始我們的爬蟲邏輯部分:
這里值得注意的是,該頁(yè)面使用 frame 框架,使用 Selenium + PhantomJS 后并不會(huì)加載 iframe 框架中的網(wǎng)頁(yè)內(nèi)容。iframe 框架相當(dāng)于在頁(yè)面中又加載了一個(gè)頁(yè)面,需要使用 Selenium 的 switch_to.frame() 方法加載(官網(wǎng)給的方法是 switch_to_frame(),但是 IDE 提醒使用前面的方法替代該方法)。
看下面的網(wǎng)頁(yè)結(jié)構(gòu),iframe 的 id 是“g_iframe”:
加載 iframe 框架中的內(nèi)容:
driver = webdriver.PhantomJS()
driver.get(self.init_url)
driver.switch_to.frame(g_iframe)
html = driver.page_source
然后找到所有的封面元素:
根據(jù)上圖的網(wǎng)頁(yè)結(jié)構(gòu)可以看出,所有的專輯信息都在 ul 標(biāo)簽里面,每一個(gè)專輯在一個(gè) li 標(biāo)簽里。li 標(biāo)簽中包含了圖片 url、專輯名字、以及專輯時(shí)間。
抓取其中的內(nèi)容就好了。
all_li = BeautifulSoup(html, lxml).find(id= m-song-module).find_all(li)
for li in all_li:
album_img = li.find(img)[src]
album_name = li.find(p , class_= dec)[title]
album_date = li.find(span , class_= s-fc3).get_text()
這里獲取到的圖片 url 依然是有圖片寬高參數(shù)的,所以要過濾寬高參數(shù):
http://p4.music.126.net/pLA1GX0KtU-vU4ZA6Cr-OQ==/1401877340532770.jpg?param=120y120
把問號(hào)后面的參數(shù)過濾掉:
end_pos = album_img.index(?) # 找到問號(hào)的位置
album_img_url = album_img[:end_pos] # 截取問號(hào)之前的內(nèi)容
圖片命名邏輯:專輯時(shí)間 + 專輯名。
專輯名可能有一些特殊字符,需要替換掉!
photo_name = album_date + – + album_name.replace(/ ,).replace(: , ,) + .jpg
再使用上一篇博文例子中的去重邏輯,修改后的爬蟲邏輯部分如下:
def spider(self):
print(Start!)
driver = webdriver.PhantomJS()
driver.get(self.init_url)
driver.switch_to.frame(g_iframe)
html = driver.page_source
self.mkdir(self.folder_path) # 創(chuàng)建文件夾
print(開始切換文件夾)
os.chdir(self.folder_path) # 切換路徑至上面創(chuàng)建的文件夾
file_names = self.get_files(self.folder_path) # 獲取文件夾中的所有文件名,類型是 list
all_li = BeautifulSoup(html, lxml).find(id= m-song-module).find_all(li)
# print(type(all_li))
for li in all_li:
album_img = li.find(img)[src]
album_name = li.find(p , class_= dec)[title]
album_date = li.find(span , class_= s-fc3).get_text()
end_pos = album_img.index(?)
album_img_url = album_img[:end_pos]
photo_name = album_date + - + album_name.replace(/ ,).replace(: , ,) + .jpg
print(album_img_url, photo_name)
if photo_name in file_names:
print(圖片已經(jīng)存在,不再重新下載)
else:
self.save_img(album_img_url, photo_name)
其實(shí)相對(duì)于上篇博文的例子,這個(gè)爬蟲的邏輯部分還是挺簡(jiǎn)潔的。
最后上一個(gè)完整的代碼:也可以從 GitHub 下載
from selenium import webdriver
from bs4 import BeautifulSoup
import requests
import os
class AlbumCover():
def __init__(self):
self.init_url = http://music.163.com/#/artist/album?id=101988 limit=120 offset=0 # 請(qǐng)求網(wǎng)址
self.folder_path = C:\D\TheBeatles # 想要存放的文件目錄
def save_img(self, url, file_name): ## 保存圖片
print(開始請(qǐng)求圖片地址,過程會(huì)有點(diǎn)長(zhǎng)...)
img = self.request(url)
print(開始保存圖片)
f = open(file_name, ab)
f.write(img.content)
print(file_name, 圖片保存成功!)
f.close()
def request(self, url): # 封裝的 requests 請(qǐng)求
r = requests.get(url) # 像目標(biāo) url 地址發(fā)送 get 請(qǐng)求,返回一個(gè) response 對(duì)象。有沒有 headers 參數(shù)都可以。 return r
def mkdir(self, path): ## 這個(gè)函數(shù)創(chuàng)建文件夾
path = path.strip()
isExists = os.path.exists(path)
if not isExists:
print(創(chuàng)建名字叫做 , path, 的文件夾)
os.makedirs(path)
print(創(chuàng)建成功!)
return True
else:
print(path, 文件夾已經(jīng)存在了,不再創(chuàng)建)
return False
def get_files(self, path): # 獲取文件夾中的文件名稱列表
pic_names = os.listdir(path)
return pic_names
def spider(self):
print(Start!)
driver = webdriver.PhantomJS()
driver.get(self.init_url)
driver.switch_to.frame(g_iframe)
html = driver.page_source
self.mkdir(self.folder_path) # 創(chuàng)建文件夾
print(開始切換文件夾)
os.chdir(self.folder_path) # 切換路徑至上面創(chuàng)建的文件夾
file_names = self.get_files(self.folder_path) # 獲取文件夾中的所有文件名,類型是 list
all_li = BeautifulSoup(html, lxml).find(id= m-song-module).find_all(li)
# print(type(all_li))
for li in all_li:
album_img = li.find(img)[src]
album_name = li.find(p , class_= dec)[title]
album_date = li.find(span , class_= s-fc3).get_text()
end_pos = album_img.index(?)
album_img_url = album_img[:end_pos]
photo_name = album_date + - + album_name.replace(/ , ).replace(: , ,) + .jpg
print(album_img_url, photo_name)
if photo_name in file_names:
print(圖片已經(jīng)存在,不再重新下載)
else:
self.save_img(album_img_url, photo_name)
album_cover = AlbumCover()
album_cover.spider()
執(zhí)行結(jié)果:
看看文件夾里面什么樣:
歷年的專輯封面已經(jīng)到手啦,還有專輯的名稱和發(fā)行日期。
四、后語(yǔ)
這個(gè)實(shí)戰(zhàn)很好的運(yùn)用了咱們之前講解的知識(shí):
使用 Selenium + PhatomJS 抓取動(dòng)態(tài)頁(yè)面
使用 Selenium 的 switch_to.frame() 加載 iframe 中的內(nèi)容
使用 requests 庫(kù)獲取圖片
使用 BeautifulSoup 庫(kù)解析抓取網(wǎng)頁(yè)內(nèi)容。
使用 os 庫(kù)創(chuàng)建文件夾和獲取文件夾中的文件名稱列表
上述就是丸趣 TV 小編為大家分享的如何用 Python 爬取網(wǎng)易云音樂輯的圖片及專輯名和專輯出版時(shí)間了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注丸趣 TV 行業(yè)資訊頻道。
向 AI 問一下細(xì)節(jié)
丸趣 TV 網(wǎng) – 提供最優(yōu)質(zhì)的資源集合!