python爬虫学习教程,爬取网易云音乐!

2019-07-14 admin

运行环境

我的运行环境如下:

系统版本

Windows10。

Python版本

Python3.5,推荐使用Anaconda 这个科学计算版本,主要是因为它自带一个包管理工具,可以解决有些包安装错误的问题。去Anaconda官网,选择Python3.5版本,然后下载安装。

IDE

我使用的是PyCharm,是专门为Python开发的IDE。这是JetBrians的产品

实战

上面提到过,网易云音乐的网页跟普通的网页相比主要有两点不同:

网页是 js 动态加载的

使用了iframe框架

所以,

首先,网页请求不能使用requests库,需要使用Selenium + PhatomJS。

其次,使用Selenium + PhatomJS后,还需要针对 iframe 做特定处理。

废话不多说,看实际操作步骤:

废话不多说,看实际操作步骤: 首先打开网页 http://music.163.com

clipboard.png

在右上角的搜索框中输入“The Beatles”,然后会有一个下拉选项,选择歌手 The Beatles (红框中的内容)。

clipboard.png

然后看到如下页面,选择红框中的“所有专辑”,点击。

clipboard.png

这样就会看见所有的专辑列表,以及下方的翻页按钮。

clipboard.png

我们需要的就是所有专辑的图片、专辑名和专辑出版时间。看到这就可以构想一下爬虫的爬取逻辑了。定位到该页面,然后获取页码,然后挨个请求页面来爬取页面中的内容。

点击一下翻页按钮看看url 有没有什么规律。

clipboard.png

点击第二页后,看到上面的地址栏!!!看到这个地址栏我都懒得翻页了。。。

limit 参数是限制一个页面加载专辑的个数

offset 参数是前面过滤多少个专辑,现在是一页12个专辑,所以第二页是offset=12,第三页offset=24,以此类推。。。

一共9页,一页12个,也不到120个。So… … 改一下url 就不用翻页了!!

limit 参数等于120,offset 参数 等于0,就搞定了!输入下面的url,看看是不是所有的专辑都加载出来了。

http://music.163.com/#/artist/album?id=101988&limit=120&offset=0

下面就开始爬虫代码了。 这里我们会用到上一篇博文中写好的几个工具方法:

'''
在学习过程中有什么不懂得可以加我的
python学习交流扣扣qun,934109170
群里有不错的学习教程、开发工具与电子书籍。
与你分享python企业当下人才需求及怎么从零基础学习好python,和学习什么内容。
'''
    def save_img(self, url, file_name): ##保存图片
        print('开始请求图片地址,过程会有点长...')
        img = self.request(url)
        print('开始保存图片')
        f = open(file_name, 'ab')
        f.write(img.content)
        print(file_name,'图片保存成功!')
        f.close()

    def request(self, url):  #封装的requests 请求
        r = requests.get(url)  # 像目标url地址发送get请求,返回一个response对象。有没有headers参数都可以。
        return r

    def mkdir(self, path):  ##这个函数创建文件夹
        path = path.strip()
        isExists = os.path.exists(path)
        if not isExists:
            print('创建名字叫做', path, '的文件夹')
            os.makedirs(path)
            print('创建成功!')
            return True
        else:
            print(path, '文件夹已经存在了,不再创建')
            return False

    def get_files(self, path): #获取文件夹中的文件名称列表
        pic_names = os.listdir(path)
        return pic_names

OK, 开始我们的爬虫逻辑部分:

这里值得注意的是,该页面使用frame 框架,使用Selenium + PhantomJS 后并不会加载iframe 框架中的网页内容。iframe 框架相当于在页面中又加载了一个页面,需要使用Selenium 的 switch_to.frame() 方法加载(官网给的方法是switch_to_frame(),但是IDE提醒使用前面的方法替代该方法)。

看下面的网页结构,iframe的id是“g_iframe”:

加载 iframe 框架中的内容:


driver = webdriver.PhantomJS()
driver.get(self.init_url)
driver.switch_to.frame("g_iframe")
html = driver.page_source

然后找到所有的封面元素:

clipboard.png

根据上图的网页结构可以看出,所有的专辑信息都在ul 标签里面,每一个专辑在一个li 标签里。li 标签中包含了图片url、专辑名字、以及专辑时间。

抓取其中的内容就好了。


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 依然是有图片宽高参数的,所以要过滤宽高参数: http://p4.music.126.net/pLA1G…

把问号后面的参数过滤掉:

end_pos = album_img.index('?')  #找到问号的位置
album_img_url = album_img[:end_pos]  #截取问号之前的内容

图片命名逻辑:专辑时间 + 专辑名。

专辑名可能有一些特殊字符,需要替换掉!

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)  # 创建文件夹
        print('开始切换文件夹')
        os.chdir(self.folder_path)  # 切换路径至上面创建的文件夹

        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('图片已经存在,不再重新下载')
            else:
                self.save_img(album_img_url, photo_name)

其实相对于上篇博文的例子,这个爬虫的逻辑部分还是挺简洁的。

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" #请求网址
        self.folder_path = "C:\D\TheBeatles" #想要存放的文件目录

    def save_img(self, url, file_name):  ##保存图片
        print('开始请求图片地址,过程会有点长...')
        img = self.request(url)
        print('开始保存图片')
        f = open(file_name, 'ab')
        f.write(img.content)
        print(file_name, '图片保存成功!')
        f.close()

    def request(self, url):  # 封装的requests 请求
        r = requests.get(url)  # 像目标url地址发送get请求,返回一个response对象。有没有headers参数都可以。
        return r

    def mkdir(self, path):  ##这个函数创建文件夹
        path = path.strip()
        isExists = os.path.exists(path)
        if not isExists:
            print('创建名字叫做', path, '的文件夹')
            os.makedirs(path)
            print('创建成功!')
            return True
        else:
            print(path, '文件夹已经存在了,不再创建')
            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)  # 创建文件夹
        print('开始切换文件夹')
        os.chdir(self.folder_path)  # 切换路径至上面创建的文件夹

        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('图片已经存在,不再重新下载')
            else:
                self.save_img(album_img_url, photo_name)

album_cover = AlbumCover()
album_cover.spider()

执行结果:

clipboard.png

看看文件夹里面什么样:

clipboard.png

[转载]原文链接:https://segmentfault.com/a/1190000019754084

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-69748.html

文章标题:python爬虫学习教程,爬取网易云音乐!

相关文章
ajax教程之ajax使用Http请求
ajax中是如何让使用http请求的呢? 在传统的JS编程中,如果您希望从服务器上的文件或数据库中得到任何的信息,或者向服务器发送信息的话,就必须利用一个 HTML 表单向服务器 GET 或 POST 数据。而用户则需要单击“提交”按钮来发...
2015-11-12
关于本教程
你应该已经知道什么? 本教程假定您有以下基本的知识: 有一个大体的了解互联网和万维网( www )。 良好的工作知识的超文本标记语言( html )。 一些编程经验。 ...
2015-11-12
JavaScript中文网:即将发布JavaSCript原创教程
JavaScript中文网:即将发布JavaSCript原创教程 ...
2015-11-12
JS教程之基础
javascript教程之什么是 JavaScript? JavaScript 被设计用来向 HTML 页面添加交互行为。JavaScript 是一种脚本语言(脚本语言是一种轻量级的编程语言)。JavaScript 由数行可执行计算机代码组...
2015-11-12
JS实现的验证身份证及获取地区功能示例
本文实例讲述了JS实现的验证身份证及获取地区功能。分享给大家供大家参考,具体如下: 这里的代码可以用来验证身份证号,并且根据身份证号来判断是哪个省份及性别 代码示例: <head > <title><&#x...
2017-03-08
element-ui中el-tree树形控件-树节点的选择(选中当前节点,获取当前id并且获取其父级id)
在element-ui的el-tree树形控件中默认获取选取当前选中id的方法是this.$refs.tree.getCheckedKeys(); 但是如果子节点不是全部选中的话,父节点算不选中。 由于我们一般想要的是就算只选中一个直接点父...
2018-12-12
Ajax教程之Ajax介绍
Ajax 由 HTML、JavaScript™ 技术、DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序。本文的作者是一位 Ajax 专家,他演示了这些技术如何协同工作 —— 从总体概述...
2015-11-12
JavaScript获取本周周一,周末及获取任意时间的周一周末功能示例
本文实例讲述了JS获取本周周一,周末及获取任意时间的周一周末功能。分享给大家供大家参考,具体如下: 项目需要获取本周及任意一天的周一及周末 需格式化,示例代码如下: <!DOCTYPE html PUBLIC "-&#x2F...
2017-03-17
node.js读取文件到字符串的方法
本文实例讲述了node.js读取文件到字符串的方法。分享给大家供大家参考。具体分析如下: Node.js是一套用来编写高性能网络服务器的JavaScript工具包,一系列的变化由此开始。比较独特的是,Node.js会假设你是在POSIX环境...
2017-03-27
js提取中文拼音首字母的封装工具类
前言 本文主要记录了如何用js提前中文拼音首字母的方法。封装一个函数,假如有需要的,可以直接拿去用。下面话不多说了,来一起看看详细的介绍吧。 原理 主要是根据中文的unicode码来进行的。主要是在收集的中文范围内查找,大家可以多收集一些。...
2018-03-13
回到顶部