一、前言


前文说过我的设计师小伙伴的设计需求,他想做一个披头士乐队历年专辑的瀑布图。

通过搜索,发现网易云音乐上有比较全的历年专辑信息加配图,图片质量还可以,虽然有大有小。

我的例子怎么都是爬取图片?(谁让你总是跟设计师小伙伴一起玩耍。。。)看来图片对于设计师来说还是有着很深的情节,那就看他用这些图片能做出什么样的作品啦,期待一下,后续会展示一下他的作品。

其实爬取网易云音乐跟之前爬取的网站稍稍有点不同,当然,爬虫写的多了就觉得套路都是固定的,见招拆招而已。

二、运行环境


我的运行环境如下:

  • 系统版本

    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

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

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

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

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

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

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

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

下面就开始爬虫代码了。

这里我们会用到上一篇博文中写好的几个工具方法:

    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
```

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

根据上图的网页结构可以看出,所有的专辑信息都在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/pLA1GX0KtU-vU4ZA6Cr-OQ==/1401877340532770.jpg?param=120y120

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

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)

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

最后上一个完整的代码: 也可以从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" #请求网址
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()

执行结果:

看看文件夹里面什么样:

历年的专辑封面已经到手啦,还有专辑的名称和发行日期。

四、后语


这个实战很好的运用了咱们之前讲解的知识:

  • 使用Selenium + PhatomJS 抓取动态页面
  • 使用Selenium 的switch_to.frame() 加载 iframe 中的内容
  • 使用requests 库获取图片
  • 使用BeautifulSoup 库解析抓取网页内容。
  • 使用os 库创建文件夹和获取文件夹中的文件名称列表

使用现有的知识编写简单的爬虫是不成问题了。接下来会讲讲爬虫框架,就从现在比较流行的Scrapy 框架讲起吧。

我得找找比较合适的例子,工作中用到的爬虫不太方便贴上来,有合适的实例我会继续更新。

有任何的疑问可以留言,就先酱紫吧。

See you then.

Python爬虫小白入门(六)爬取披头士乐队历年专辑封面-网易云音乐的更多相关文章

  1. Python爬虫实战一之爬取糗事百科段子

    大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧.那么这次为大家带来,Python爬取糗事百科的小段子的例子. 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把 ...

  2. Python爬虫实战二之爬取百度贴吧帖子

    大家好,上次我们实验了爬取了糗事百科的段子,那么这次我们来尝试一下爬取百度贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作. 前言 亲爱的们,教程比较旧了,百度贴吧页面可能改版,可能代码不 ...

  3. 转 Python爬虫实战二之爬取百度贴吧帖子

    静觅 » Python爬虫实战二之爬取百度贴吧帖子 大家好,上次我们实验了爬取了糗事百科的段子,那么这次我们来尝试一下爬取百度贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作. 本篇目标 ...

  4. 转 Python爬虫实战一之爬取糗事百科段子

    静觅 » Python爬虫实战一之爬取糗事百科段子 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致 ...

  5. python爬虫学习01--电子书爬取

    python爬虫学习01--电子书爬取 1.获取网页信息 import requests #导入requests库 ''' 获取网页信息 ''' if __name__ == '__main__': ...

  6. python爬虫:了解JS加密爬取网易云音乐

    python爬虫:了解JS加密爬取网易云音乐 前言 大家好,我是"持之以恒_liu",之所以起这个名字,就是希望我自己无论做什么事,只要一开始选择了,那么就要坚持到底,不管结果如何 ...

  7. Python爬虫:为什么你爬取不到网页数据

    前言: 之前小编写了一篇关于爬虫为什么爬取不到数据文章(文章链接为:Python爬虫经常爬不到数据,或许你可以看一下小编的这篇文章), 但是当时小编也是胡乱编写的,其实里面有很多问题的,现在小编重新发 ...

  8. Python爬虫小白入门(四)PhatomJS+Selenium第一篇

    一.前言 在上一篇博文中,我们的爬虫面临着一个问题,在爬取Unsplash网站的时候,由于网站是下拉刷新,并没有分页.所以不能够通过页码获取页面的url来分别发送网络请求.我也尝试了其他方式,比如下拉 ...

  9. Python爬虫实战一之爬取QQ音乐

    一.前言   前段时间尝试爬取了网易云音乐的歌曲,这次打算爬取QQ音乐的歌曲信息.网易云音乐歌曲列表是通过iframe展示的,可以借助Selenium获取到iframe的页面元素, 而QQ音乐采用的是 ...

随机推荐

  1. bootstrap基本标签总结2

    [布局]bootstrap基本标签总结2   缩略图 <div class="container"> <div class="row"> ...

  2. POJ 2553 The Bottom of a Graph (强连通分量)

    题目地址:POJ 2553 题目意思不好理解.题意是:G图中从v可达的全部点w,也都能够达到v,这种v称为sink.然后升序输出全部的sink. 对于一个强连通分量来说,全部的点都符合这一条件,可是假 ...

  3. 为Pythonic论坛添加一个“专题”功能(续)

    上篇博文<为Pythonic论坛添加一个“专题”功能>,在模板的层次上对发帖进行了限制.也就是根据用户是否拥有权限来决定是否显示发帖框. 但是自从这么“投机取巧”的写完模板后,整夜辗转反侧 ...

  4. ubuntu下使用openocd+jlink进行STM32开发调试

    安装openocd就不用多说了,使用 apt-get install openocd 这个命令就可以做到. 对于使用stm32w系列的MCU,需要下载新的openocd-0.7及以上版本才能支持.0. ...

  5. jquery背景动画插件使用

    在网页制作动画特效的时候,有时候想通过背景插入图片,然后通过控制背景显示的位置来实现一些动画效果,这样就不用使用绝对定位控制left和top来实现动画效果!但是jquery本身的动画函数是不支持背景动 ...

  6. CF:Problem 427C - Checkposts良好的沟通 Tarjan算法

    tarjan算法的第一个问题 喷我的脸....手写叠式开成BOOL,我一直在找错了... #include<cstdio> #include<cstring> #include ...

  7. 解决ZF2_PATH environment

    本方法基于:ZendFramework 2.1.4版本在WIN7下构建,其他版本的安装方式相差不大. 操作之前您需要搭建好PHP运行环境,保证PHP版本不低于PHP 5.3.3,并且去http://f ...

  8. MVC5搜索/查询 流程功能的实现

    接着上次的篇幅,我们这篇手动来写一个查询的流程代码!  搜索/查询 流程功能的实现 那现在要做搜索(查询)功能我们第一步应该做什么呢!第一次是不是我们应该去Controller(控制器)里去搞一个搜索 ...

  9. Express安装入门与模版引擎ejs

    Express安装入门与模版引擎ejs 目录 前言 Express简介和安装 运行第一个基于express框架的Web 模版引擎 ejs express项目结构 express项目分析 app.set ...

  10. C#中的深复制与浅复制

    C#中分为值类型和引用类型,值类型的变量直接包含其数据,而引用类型的变量则存储对象的引用. 对于值类型,每个变量都有自己的数据副本,对一个变量的操作不可能影响到另一个变量.如 class Progra ...