天天看点

Python爬虫-selenium爬取网易云歌单(一)工欲善其事必先利其器-安装工具(二)实战

文章目录

  • (一)工欲善其事必先利其器-安装工具
    • Selenium
    • 浏览器
  • (二)实战

(一)工欲善其事必先利其器-安装工具

Selenium

Selenium是一个强大的网络数据采集工具,其最初是为网站自动化测试而开发的。近几年,它还被广泛用于获取精确的网站快照,因为它们可以直接运行在浏览器上。Selenium 库是一个在WebDriver 上调用的API。WebDriver 有点儿像可以加载网站的浏览器,但是它也可以像BeautifulSoup对象一样用来查找页面元素,与页面上的元素进行交互(发送文本、点击等),以及执行其他动作来运行网络爬虫。安装方式与其他Python第三方库一样。

pip install Selenium

浏览器

Selenium 自己不带浏览器,它需要与第三方浏览器结合在一起使用。例如,如果你在Firefox 上运行Selenium,可以直接看到一个Firefox 窗口被打开,进入网站,然后执行你在代码中设置的动作。虽然这样可以看得更清楚,但不适用于这个爬虫程序,爬一页就打开一页效率太低,所以我用一个叫PhantomJS的工具代替真实的浏览器。

PhantomJS:是一个“无头”(headless)浏览器。它会把网站加载到内存并执行页面上的JavaScript,但是它不会向用户展示网页的图形界面。把Selenium和PhantomJS 结合在一起,就可以运行一个非常强大的网络爬虫。

官方网站下载:http://phantomjs.org/download.html

然后把可执行文件拷贝到Python安装目录的Scripts文件夹。

(二)实战

1.爬取歌单的名字,播放量,链接放入一个csv文件;

2.将歌单封面和歌单中的歌曲下载到文件中。

网易云站外播放器链接:http://music.163.com/song/media/outer/url?id=

加上歌曲id号即可以获取歌曲,如:http://music.163.com/song/media/outer/url?id=476592630.mp3

网易云歌单链接(第一页):https://music.163.com/#/discover/playlist/?order=hot&cat=全部&limit=35&offset=0

“F12”分析一下:

Python爬虫-selenium爬取网易云歌单(一)工欲善其事必先利其器-安装工具(二)实战

播放数nb (number broadcast):59340

封面 msk (mask):有标题(title)和url

同理,也可以找到“下一页”的url,最后一页的url是“javascript:void(0)”

Python爬虫-selenium爬取网易云歌单(一)工欲善其事必先利其器-安装工具(二)实战

这就可以做一个循环,来获取数据:

url="https://music.163.com/#/discover/playlist/?order=hot&cat=%E5%85%A8%E9%83%A8&limit=35&offset=0"
while url!='javascript:void(0)':
           

网易云有反爬虫机制:

1.User Agent:

Python爬虫-selenium爬取网易云歌单(一)工欲善其事必先利其器-安装工具(二)实战

找到User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6801.400 QQBrowser/10.3.2960.400

如果是使用入门的requests,BeautifulSoup来爬取数据就需要添加headers,不然服务器会识别爬虫,获取不到数据;

headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6788.400 QQBrowser/10.3.2714.400"}
html=requests.get(url,headers=headers)
           

2.frame框架:

Python爬虫-selenium爬取网易云歌单(一)工欲善其事必先利其器-安装工具(二)实战

网易云用了frame框架,使用BeautifulSoup的find()方法获取class和tag是获取不到数据的,只能使用xpath;

而这里使用Selenium,就直接使用switch_to.frame()方法;

先完成第1步:

from selenium import webdriver
import csv

#准备好储存数据的csv文件
csv_file=open("playlist.csv","a",newline="",encoding='utf-8')
writer=csv.writer(csv_file)
writer.writerow(['歌单名','播放量','链接'])

#歌单第一页
url="https://music.163.com/#/discover/playlist/?order=hot&cat=%E5%85%A8%E9%83%A8&limit=35&offset=0"
#用PhantomJS接口创建一个Selenium的WebDriver
driver=webdriver.PhantomJS()

#解析每一页,到最后一页
while url!='javascript:void(0)':
    print("访问地址:",url)
    #用WebDriver加载界面
    driver.get(url)
    #切换到内容的iframe
    driver.switch_to.frame("g_iframe")
    #获取歌单标签
    data=driver.find_element_by_id("m-pl-container").find_elements_by_tag_name("li")
    for i in range(len(data)):
        src=data[i].find_element_by_class_name("j-flag").get_attribute('src')
        a=data[i].find_element_by_class_name("msk")
        name=a.get_attribute('title')   #歌单名字
        print("歌单名:",name)
        nb=data[i].find_element_by_class_name("nb").text #播放量
        print("播放量:",nb)
        hf=a.get_attribute('href') #链接
        print("链接:",hf)
        
        #将数据写入csv文件
        writer.writerow([name,nb,hf])

    url=data[i].find_element_by_xpath('//*[@id="m-pl-pager"]/div/a[11]').get_attribute('href')

csv_file.closed()
           

爬取数据结果:

Python爬虫-selenium爬取网易云歌单(一)工欲善其事必先利其器-安装工具(二)实战

完成第2步(网易云维护升级,站外播放器的链接失效了,访问都是404,所以将歌曲链接存为.txt文件):

from selenium import webdriver
import csv
import os
import requests
import re
import urllib

#创建以歌单名为文件名的文件
def creatFile(url,name):
    if not os.path.isdir(os.getcwd()+"/"+name):
        os.mkdir(os.getcwd()+"/"+name)
    img=requests.get(url)
    with open(os.getcwd()+"/"+name+"/"+"封面.jpg",'wb') as f:
        f.write(img.content)

#获得歌单内歌曲界面
def getMusicPage(name,url):
    driver=webdriver.PhantomJS()
    driver.get(url)
    driver.switch_to.frame("g_iframe")
    info=driver.find_element_by_xpath('//table[@class="m-table "]/tbody').find_elements_by_tag_name("tr")
    for i in range(len(info)):
        musicName=info[i].find_element_by_tag_name("b").get_attribute('title').replace('\xa0','')
        print(musicName)
        title=validateTitle(musicName)
        hf=info[i].find_element_by_tag_name("a").get_attribute('href')
        #song_id=hf.strip('https://music.163.com/song?id=85575')
        #song_url="http://music.163.com/song/media/outer/url?id="+song_id
        #print(song_url)
        downloadMusic(name,title,hf)

#正则表达式处理创建文件夹文件名时的非法字符
def validateTitle(title):
    rstr=r"[\/\\\:\*\?\"\<\>\|]"  # '/ \ : * ? " < > |'
    new_title=re.sub(rstr,"_",title) #将非法字符替换为下划线
    return new_title

#将歌曲链接存入文件
def downloadMusic(name,musicName,url):
    if not os.path.isdir(os.getcwd()+"/"+name+"/"+musicName):
        os.mkdir(os.getcwd()+"/"+name+"/"+musicName)
    with open(os.getcwd()+"/"+name+"/"+musicName+"/"+"链接.txt","w") as f:
        f.write(url)
    '''
    #下载歌曲(已失效)
    path=os.getcwd()+"/"+name+"/{}.mp3".format(musicName)
    with open(path,'wb') as f:
        try:
            urllib.request.urlretrieve(url,path)
        except BaseException:
            print("下载失败:"+musicName)
            pass
    '''

if __name__=='__main__':
    csv_file=open("playlist.csv","a",newline="",encoding='utf-8')
    writer=csv.writer(csv_file)
    writer.writerow(['歌单名','播放量','链接'])

    #歌单第一页
    url="https://music.163.com/#/discover/playlist/?order=hot&cat=%E5%85%A8%E9%83%A8&limit=35&offset=0"
    #用PhantomJS接口创建一个Selenium的WebDriver
    driver=webdriver.PhantomJS()

    #解析每一页,到最后一页
    while url!='javascript:void(0)':
        print("访问地址:",url)
        #用WebDriver加载界面
        driver.get(url)
        #切换到内容的iframe
        driver.switch_to.frame("g_iframe")
        #获取歌单标签
        data=driver.find_element_by_id("m-pl-container").find_elements_by_tag_name("li")
        for i in range(len(data)):
            src=data[i].find_element_by_class_name("j-flag").get_attribute('src')
            a=data[i].find_element_by_class_name("msk")
            name=a.get_attribute('title')   #歌单名字
            fileName=validateTitle(name)
            #创建文件存储歌单
            creatFile(src,fileName)
            hf=a.get_attribute('href') #链接
            #获得歌单链接,获得歌曲信息
            getMusicPage(fileName,hf)


        url=data[i].find_element_by_xpath('//*[@id="m-pl-pager"]/div/a[11]').get_attribute('href')

           

创建文件夹时使用相对路径创建文件夹,爬取结果:

以歌单名创建的文件夹:
           
Python爬虫-selenium爬取网易云歌单(一)工欲善其事必先利其器-安装工具(二)实战
以歌曲名创建的文件夹:
           
Python爬虫-selenium爬取网易云歌单(一)工欲善其事必先利其器-安装工具(二)实战
文件夹中为歌曲播放链接:
           
Python爬虫-selenium爬取网易云歌单(一)工欲善其事必先利其器-安装工具(二)实战

继续阅读