当前位置:   article > 正文

爬虫基础之浅爬一点音乐数据_爬取qq音乐

爬取qq音乐

本次分享是对QQ音乐网页中部分歌手前十首热门歌曲的基本信息(歌手名,个人简介,歌曲名,所在专辑和发行时间)进行一个爬取收集并录入Excel文件中。

首先让我们先了解一下爬虫的基本流程。

爬虫程序的基本流程

  • 获取网页

python中提供了requests、urllib等很多库来帮助我们获取页面信息。本篇文章使用的是requests库

  • 提取信息

我们运用第三方库获取的网页信息是原始的,没有经过处理的数据,我们需要通过处理筛选提取自己所需要的数据,在这里我们利用的是bs4(BeautiSoup)库来提取信息的。

  • 保存信息

我们通过筛选获取到的大量数据,我们可以按照用多种形式来保存。如:可以保存为txt文本、Excel文件或者存储到数据库中。甚至可以直接存储到服务器中。大家可以根据自己后期对该数据的使用或者查看方式来选择保存信息的方式。

  • 自动化运行

爬虫的工作复杂起来是一个庞大繁琐的程序,这时我们可以通过一些自动化工具帮助我们的爬虫运行。

结果如图所示:

 整体是一个xls文件,里面包含多张表格分别对应每个歌手的信息。接下来让我们一起来分析一下这个结果的实现过程。

第一步 分析网页

 如何找到我们需要的数据的第一步也是最重要的一步便是分析网页,首先让我们先打开QQ音乐歌手界面的网页,并按【Fn+F12】调出开发者工具。

以许嵩为例分析网页代码,选中他可以到跳转代码处

 展开该处代码我们会发现这是一个层级标签代码,

在这段代码中我们可以分析出几个重点内容:

  • 他是一个层级标签的代码,有两层
  • 两个标签的一些属性值:class值,title值和href值(是我们常用到的)
  • 他叫许嵩(不是废话的废话)

让我们对许嵩进行一个深入的了解,点击他的名字进入他的主页后点击全部进入以下页面,然后再次打开开发者工具

 根据自己对数据的要求,除去他的姓名,我们还需要知道他的个人简介,歌曲名,专辑名,歌曲时长和发行时间,在本页面我们可以找到前四个要求的位置和代码

 

 在此时,我们点击这首歌跳转的网页会有一个有趣的现象

 根据以上分析,我们可以联想到,如果利用爬虫程序在QQ音乐游走获取数据,所需要的url几乎可以分为两个部分

  • http://y.qq.com
  • 某个可以可以跳转的对象标签的href值

 那么可以用python中的字符串拼接,对网页进行深度或者广度的爬取

 综上,我们可以总结出这只“爬虫”的轨迹如下图所示:

 一个歌手是这样走的路线,那么多个歌手也是这么走,大家可以多分析几位歌手来体会一下有趣的爬虫历程。

第二步 代码实现

准备第三库

  1. import requests
  2. from bs4 import BeautifulSoup
  3. import xlwt


Requests库

Python requests 是一个常用的 HTTP 请求库,可以方便地向网站发送 HTTP 请求,并获取响应结果。导入后就可以发送 HTTP 请求,使用 requests 提供的方法向指定 URL 发送 HTTP 请求。

BeautiSoup库

我们简称bs4库,他可以从 HTML 或 XML 文档中快速地提取指定的数据。帮助我们筛选提取数据,Beautiful Soup 语法简单,使用方便,并且容易理解

xlwt库

在获取提取信息数据之后,保存数据我选择了xlwt库,将数据写入excel文件。

功能函数实现

表格样式选择

目的是为了让我们的表格更加美观

  1. def create_table_style(n):
  2. if(n==1):
  3. style = xlwt.XFStyle() # 初始化样式
  4. font = xlwt.Font() # 为样式创建字体
  5. font.name = 'Times New Roman'
  6. font.height = 20 * 13 # 字体大小,11为字号,20为衡量单位
  7. font.bold = True # 黑体
  8. font.underline = False # 下划线
  9. font.italic = True # 斜体字
  10. al = xlwt.Alignment()
  11. al.horz = 0x02 # 设置水平居中
  12. al.vert = 0x01 # 设置垂直居中
  13. borders = xlwt.Borders() # Create Borders
  14. borders.left = xlwt.Borders.THIN # DASHED虚线,NO_LINE没有,THIN实线
  15. borders.right = xlwt.Borders.THIN # borders.right=1 表示实线
  16. borders.top = xlwt.Borders.THIN
  17. borders.bottom = xlwt.Borders.THIN
  18. borders.left_colour = 0x40
  19. borders.right_colour = 0x40
  20. borders.top_colour = 0x40
  21. borders.bottom_colour = 0x40
  22. pattern = xlwt.Pattern()
  23. pattern.pattern = xlwt.Pattern.SOLID_PATTERN
  24. pattern.pattern_fore_colour = 29
  25. style.font = font # 设定样式
  26. style.borders = borders
  27. style.pattern = pattern
  28. style.alignment = al
  29. style.alignment.wrap = 1
  30. return style
  31. if (n == 2):
  32. style = xlwt.XFStyle() # 初始化样式
  33. font = xlwt.Font() # 为样式创建字体
  34. font.name = 'Times New Roman'
  35. font.height = 20 * 13 # 字体大小,11为字号,20为衡量单位
  36. font.bold = True # 黑体
  37. font.underline = False # 下划线
  38. font.italic = False # 斜体字
  39. al = xlwt.Alignment()
  40. al.horz = 0x02 # 设置水平居中
  41. al.vert = 0x01 # 设置垂直居中
  42. borders = xlwt.Borders() # Create Borders
  43. borders.left = xlwt.Borders.THIN # DASHED虚线,NO_LINE没有,THIN实线
  44. borders.right = xlwt.Borders.THIN # borders.right=1 表示实线
  45. borders.top = xlwt.Borders.THIN
  46. borders.bottom = xlwt.Borders.THIN
  47. borders.left_colour = 0x40
  48. borders.right_colour = 0x40
  49. borders.top_colour = 0x40
  50. borders.bottom_colour = 0x40
  51. style.font = font # 设定样式
  52. style.borders = borders
  53. style.alignment = al
  54. style.alignment.wrap = 1
  55. return style
'
运行

设置行高和列宽

一切为了美观

  1. def set_column_width(sum,worksheet):
  2. for i in range(sum):
  3. worksheet.col(i).width = 320 * 30
  4. def set_row_height(sum,worksheet):
  5. for i in range(sum):
  6. tall_style = xlwt.easyxf('font:height 480;') # 36pt
  7. worksheet.row(i).set_style(tall_style)
'
运行

设置每张表的表头

对于文件中的每一个表,他的第一行为歌手的名字,所以写了一个函数来实现

  1. def table_head(data, data_table, style):
  2. data_table.write_merge(0, 0, 0, 3 ,data, style) #输入时合并单元格
  3. # (0,0,0,3)表示合并的是第一行的1~3列
'
运行

录入歌手个人简介

  1. def singer_infto_entry_table(data, data_table, style1,style2):
  2. data_table.write_merge(1,1,0,3, "简介", style1)
  3. data_table.write_merge(2,5,0,3, data,style2)
  4. # 输入时合并单元格
  5. # (1,1,0,3)表示合并的是第二行的1~3列
  6. # (2,5,0,3)表示将3~6行的1~3列都给合并了
'
运行

录入歌曲基本信息属性

实现的是这一部分

  1. def table_header(bs, data,data_table, style):
  2. for i in range(len(data)):
  3. data_table.write(6,i,data[i],style)
'
运行

以上是对Excel文件表格样式等做了规范美观的函数

获取网页数据

  1. def get_html_data(url):
  2. """
  3. 获取网页数据,生成bs对象
  4. :param url: 所要爬取的网页的网址
  5. :return: 返回一个bs对象,用于后续的数据获取
  6. """
  7. r1 = requests.get(url, 'lxml')
  8. r1.encoding = 'utf-8'
  9. bs_1 = BeautifulSoup(r1.text, 'lxml')
  10. return bs_1
'
运行

获取歌手个人简介

  1. def get_singer_brief_info(bs):
  2. """
  3. 获取获取歌手的姓名和个人简介
  4. :param bs: 提供提取数据的手段方法的bs对象
  5. :return: 返回歌手的姓名和个人简介
  6. """
  7. list = bs.select("div[class='data__cont']") #用bs中的select方法找到class属性值等于 data__cont的数据集
  8. # print(list)
  9. singer_name = ''
  10. singer_info = ''
  11. for li in list:
  12. singer_name = li.div.h1.string # 遍历该数据集去找到所需要的信息
  13. singer_info = li.find("div", class_="data__desc_txt").string
  14. return singer_name, singer_info
'
运行

获取歌曲基本属性

  1. def get_the_songs_header(bs):
  2. """
  3. :param bs: 提供提取数据的手段方法的bs对象
  4. :return: 返回我们需要获得的歌曲的信息头
  5. """
  6. list = []
  7. song_list = bs.find_all(attrs={'class': 'songlist__header'})
  8. for h in song_list:
  9. for li in h:
  10. content = li.string
  11. list.append(content)
  12. list.append("发行时间")
  13. return list
'
运行

录入每个歌手热门歌曲的信息

  1. def song_entry_table(bs,datatable,style):
  2. """
  3. 将每个歌手的歌曲信息录入表格
  4. :param bs: 提供提取数据的手段方法的bs对象
  5. :param datatable: 表格对象
  6. :param style: 表格的样式
  7. :return:
  8. """
  9. song_list = bs.find_all(attrs={'class': 'songlist__item'}) # 根据对网页的分析,找到attrs={'class': 'songlist__item'}的代码部分就可以找到自己想要的数据
  10. song_name = []
  11. song_group = []
  12. song_time = []
  13. # 先将信息加入列表,再遍历录入表格对象中
  14. for h in song_list:
  15. song_name.append(h.find(attrs={'class': 'songlist__songname_txt'}).find('a')['title']) # 对于多级标签的代码筛选查找可以多次调用find方法
  16. try:
  17. # 通过分析网站会发现不是所有歌都有专辑,所以对获取专辑名字的代码进行异常处理,一旦触发异常就录入没有专辑的字样
  18. song_group.append(h.find(attrs={'class': 'songlist__album'}).find('a').text)
  19. except AttributeError:
  20. song_group.append("无专辑")
  21. song_time.append(h.find(attrs={'class': 'songlist__time'}).text)
  22. for i in range(len(song_name)):
  23. datatable.write(i+7,0,song_name[i],style)
  24. datatable.write(i+7,1,song_group[i],style)
  25. datatable.write(i+7,2,song_time[i],style)
'
运行

获取歌曲发行时间

  1. def get_release_time(bs):
  2. """
  3. 获取歌曲发行时间
  4. :param bs: 提供提取数据的手段方法的bs对象
  5. :return:返回该歌手歌曲发行时间的列表
  6. """
  7. # 实现思想,歌曲详情网页网址由两部分组成,我们可以用一个列表将该歌手的每首歌的href属性值都找到,再分别和first_url = 'https://y.qq.com'进行拼接获得我们即将请求访问的下一个网页网址
  8. song_list = bs.find_all(attrs={'class': 'songlist__item'})
  9. first_url = 'https://y.qq.com'
  10. second_url = []
  11. for h in song_list:
  12. second_url.append(h.find(attrs={'class': 'songlist__songname_txt'}).find('a')['href'])
  13. time_list = []
  14. song_url = first_url + second_url[0]
  15. r = requests.get(song_url, 'lxml')
  16. r.encoding = 'utf-8'
  17. bs2 = BeautifulSoup(r.text, 'lxml')
  18. # 循环分别访问每首歌的详情网页获取发行时间数据加入time_list
  19. for i in range(len(second_url)):
  20. song_url = first_url + second_url[i]
  21. r = requests.get(song_url, 'lxml')
  22. r.encoding = 'utf-8'
  23. bs2 = BeautifulSoup(r.text, 'lxml')
  24. i = 4
  25. try:# 通过分析网页我们会发现,每首歌的详细介绍可能不同,就会导致我们的发行时间的位置不同,采用异常处理,一旦超过索引,就往前继续遍历,直到找不到发行时间,降低录入数据的错误率
  26. time_list.append(bs2.find_all(attrs={'class': 'data_info__item_song'})[i].text[5:])
  27. except IndexError:
  28. while i >=0:
  29. i-=1
  30. try:
  31. time_list.append(bs2.find_all(attrs={'class': 'data_info__item_song'})[i].text[5:])
  32. except IndexError:
  33. continue
  34. else:
  35. break
  36. return time_list
'
运行

录入歌曲发行时间

  1. def set_release_time(data,data_table,style):
  2. """
  3. 将发行时间录入表格
  4. :param data: 通过get_release_time函数获得的发行时间列表
  5. :param data_table:
  6. :param style:
  7. :return:
  8. """
  9. for i in range(len(data)):
  10. data_table.write(i+7,3,data[i],style)
'
运行

获取所有歌手页面的网址信息

  1. def get_singers_links():
  2. """
  3. 在歌手总页面获取所有歌手的主页面
  4. :return: 返回一个歌手:url的字典集
  5. """
  6. url = 'https://y.qq.com/n/ryqq/singer_list'
  7. bs = get_html_data(url)
  8. href_list = []
  9. name_list = []
  10. first_link_list = bs.find_all(attrs={'class':'singer_list_txt__link js_singer'})
  11. for li in first_link_list:
  12. name_list.append(li["title"])
  13. href_list.append(li["href"])
  14. singer_url_dict = dict(zip(name_list,href_list))
  15. return singer_url_dict
'
运行

生成每个歌手的表格

  1. def create_singer_sheet(data):
  2. """
  3. 生成xls文件
  4. :param data: 是通过get_singers_links函数获得的所有歌手页面href值的数据集,是一个字典
  5. :return:
  6. """
  7. first_url = 'https://y.qq.com/'
  8. last_url = '/song'
  9. for person in data: # 页面中获取到几个歌手href值就会循环几次,文件中就会有几个表
  10. url = first_url+data[person]+last_url #拼接出完整的网址
  11. # 调用函数
  12. bs = get_html_data(url)
  13. singer_info = get_singer_brief_info(bs)
  14. print(singer_info)
  15. header_list = get_the_songs_header(bs)
  16. worksheet = workbook.add_sheet(singer_info[0])
  17. set_column_width(4,worksheet)
  18. set_row_height(18,worksheet)
  19. style1 = create_table_style(1)
  20. style2 = create_table_style(2)
  21. table_head(singer_info[0], worksheet, style1)
  22. singer_infto_entry_table(singer_info[1], worksheet, style1,style2)
  23. table_header(bs,header_list, worksheet, style1)
  24. song_entry_table(bs,worksheet,style2)
  25. time_list = get_release_time(bs)
  26. set_release_time(time_list,worksheet,style2)
'
运行

调用主函数

  1. if __name__ == '__main__':
  2. singer_url_dict = get_singers_links()
  3. create_singer_sheet(singer_url_dict)
  4. workbook.save("歌手热门前十歌曲基本信息.xls")

第三步 总结

虽然这只是一个简单的实例但是我们可以总结到关于爬虫的一些重要思想

  1. 分析网页很重要,代码实现只是借助第三方库现成的函数将你分析的过程加以具象化并给出可视化结果
  2. 分步骤进行,虽然整体来看,可以发现我有一些 函数也可以合并成一个,但是在我们没有完全熟练的时候,想到一步做一个函数是最直观的学习过程,后期再精简效率也会变快,我们需要的就是这个思考的过程

以上是我本次python爬虫简单实例的拙见和分享,欢迎大家参考和指正(*^▽^*)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/1015731
推荐阅读
相关标签
  

闽ICP备14008679号