专栏首页一个爱吃西瓜的程序员用23行代码爬取豆瓣音乐top250

用23行代码爬取豆瓣音乐top250

豆瓣对于爬虫十分友好,而且豆瓣上面又有各种电影图书音乐等资源,是我们学习爬虫一个很不错的锻炼目标。基本上每个学习爬虫的人都会拿豆瓣来练练手。

网上有各种爬取豆瓣电影top250的教程,虽然豆瓣音乐top250和豆瓣电影top250的爬取十分类似,但是我大致对比了一下,我这种方法应该是最简单的,仅需要23行代码。好吧,如果你有更简单的方法,欢迎给我评论留言交流交流,共同进步。

抓取目标:豆瓣音乐top250的歌名、作者(专辑)、评分和歌曲链接

使用工具:requests + lxml + xpath。

我认为这种工具组合是最适合初学者的,requests比python自带的urllib库好用,功能更强大。关于requests的使用方法,建议看它的官方文档: http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

使用lxml来解析网页,速度是最快的,至少比BeatifulSoup快。关于lxml的使用方法,建议看这个:http://lxml.de/

而xpath更是傻白甜的使用方式:直接在浏览器中复制即可,如果想要掌握xpath更具体的语法,建议看w3school的xpath教程:http://www.w3school.com.cn/xpath/

首先目标url是:https://music.douban.com/top250?start=0

点击下一页,我们多观察几个页面的url:

我们会发现url的start=是以25的倍数增长的,起始为start=0,然后是start=25,每页25首音乐,一共十页。

所以,我们可以使用一个for循环来得出这十个页面的url:

for i in range(10):    
    # 一共有10个页面,每个页面25首音乐
    url = "https://music.douban.com/top250?start={}".format(i * 25)

关于format()函数的使用方法,可以看菜鸟教程上的讲解:http://www.runoob.com/python/att-string-format.html

关于range()函数的使用方法,可以看菜鸟教程上的讲解:http://www.runoob.com/python/python-func-range.html

然后我们使用requests.get()来进行网页请求:

import requests
headers = {"User_Agent": "Mozilla/5.0(compatible; MSIE 5.5; Windows 8)"}
data = requests.get(url, headers=headers).text

使用lxml来解析网页:

from lxml import etree
s = etree.HTML(data)

接下来我们开始提取数据,打开目标页面,将每首音乐的完整信息的xpath信息复制下来:

重复这样的操作,多复制几首音乐的xpath信息,观察它的规律:

//*[@id="content"]/div/div[1]/div/table[1]
//*[@id="content"]/div/div[1]/div/table[2]
//*[@id="content"]/div/div[1]/div/table[3]

这样子规律就很明显了,每首音乐就是table后的序号不同。只要我们将序号去掉,就可以提取所有音乐的全部信息了:

# 歌曲整体的xpath
musics = s.xpath('//*[@id="content"]/div/div[1]/div/table')

我们再使用同样的方法来获取歌名的xpath信息:

多复制几个歌名信息的xpath来对比一下:

# 歌名的xpath
# //*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div/a
# //*[@id="content"]/div/div[1]/div/table[2]/tbody/tr/td[2]/div/a

这是注意一下, 上面的xpath路径中,/tbody是多余的,我们要将其删掉,不然会出错,所以,有时候直接在浏览器复制xpath信息也不一定靠谱,这里要注意一下。

这样我们就可以提取出每首歌的歌名:

for music in musics:
    music_name = music.xpath('./tr/td[2]/div/a/text()')[0].strip()

如果不加[0],我们得到的结果将是一个list类型,每个结果都被中括号[]裹起来,比较碍眼,所以使用[0]取出list的第一个值就可以了。strip()函数可以去除多余的空格。

还有,音乐的链接和名字的xpath路径是相同的,只是一个取href值,一个取text值。 所以每首歌的链接如下:

for music in musics:
    music_name = music.xpath('./tr/td[2]/div/a/@href')[0]

我们再使用同样的方法复制作者(专辑)的xpath信息:

多复制几个作者的xpath信息来对比一下:

# //*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div/p[1]
# //*[@id="content"]/div/div[1]/div/table[2]/tbody/tr/td[2]/div/p[1]

同样要将/tbody从xpath路径中删掉,这样我们可以提取到每首歌的作者信息:

for music in musics:
    music_author = music.xpath('./tr/td[2]/div/p[1]/text()')[0].strip()

我们还使用同样的方法复制评分的xpath信息:

多复制几个评分的xpath信息来对比一下:

# //*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div/div/span[2]
# //*[@id="content"]/div/div[1]/div/table[2]/tbody/tr/td[2]/div/div/span[2]

同理,我们就可以提取出每首歌的评分了:

for music in musics:
    music_score = music.xpath('./tr/td[2]/div/div/span[2]/text()')[0]

到现在,我们已经获取了我们想要的所有信息。现在来整合一下代码,存储为TXT文件:

import requests
from lxml import etree
import time

with open("豆瓣音乐top250.txt", "w", encoding="utf-8") as f:    
    for i in range(10):        
        # 一共有10个页面,每个页面25首音乐
        url = "https://music.douban.com/top250?start={}".format(i * 25)
        headers = {"User_Agent": "Mozilla/5.0(compatible; MSIE 5.5; Windows 8)"}
        data = requests.get(url, headers=headers).text
        s = etree.HTML(data)        
        
        # 歌曲整体的xpath
        musics = s.xpath('//*[@id="content"]/div/div[1]/div/table')
        time.sleep(2)        
        
        for music in musics:
            music_name = music.xpath('./tr/td[2]/div/a/text()')[0].strip()  # 歌名
            music_author = music.xpath('./tr/td[2]/div/p[1]/text()')[0].strip()  # 作者
            music_score = music.xpath('./tr/td[2]/div/div/span[2]/text()')[0]  # 评分
            music_href = music.xpath('./tr/td[2]/div/a/@href')[0]  # 链接

            f.write("{} {} {} {}\n".format(music_name, music_author, music_score, music_href))

如上,一共23行代码。

爬取结果如下:

本来我想存为CSV文件的,结果发现有的歌曲有多个歌手,而且几个歌手之间是用逗号(,)分开的,这就和CSV中的逗号产生了混淆,导致结果比较错乱。好吧,我暂时不知道存为CSV格式时,怎样消除其本身携带的逗号产生的影响。

当然,同样的爬取思路,我们还可以爬取豆瓣电影top250、豆瓣图书top250。只需要将url和xpath路径修改一下就可以了。

每天学习一点点,每天进步一点点。

本文分享自微信公众号 - 小白客(youcoding),作者:爱吃西瓜的番茄酱

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-12-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 学习SQL【4】-聚合与排序

    随着表中记录(数据行)的不断积累,存储数据逐渐增加,有时我们可能希望计算出这些数据的合计值或者平均值等,这个时候就需要使用SQL语句的汇总操作等方法。 一:对表...

    爱吃西瓜的番茄酱
  • Python基础学习-if 语句

    一:条件测试 1:检查是否相等 例: ? 输出: ? 2:使用and & or检车多个条件 例: ? 输出: ? 3:检查特定值是否包含在列表中 例: ? 输...

    爱吃西瓜的番茄酱
  • 常用SQL语句和语法汇总

    近几年数据库发挥了越来越重要的作用,这其中和大数据、数据科学的兴起有不可分割的联系。学习数据库,可以说是每个从事IT行业的必修课。你学或不学,它就在那里;你想或...

    爱吃西瓜的番茄酱
  • box-sizing

            在通常的网页布局都是由一个个div等元素构成盒子形成形形色色的网页结构,在网页的构成中我们还要进行各种元素的修饰,叫做:盒子模型.

    十月梦想
  • 网页html结构搭建方法总结

    windseek
  • 页面引入CSS的四种方式及区别

    一个前端页面(原生)由HTML+CSS+JS+Image组成,页面效果由CSS负责,好的页面会吸引用户访问、停留。那么页面是如何靠css来达到效果的呢?下面说说...

    申霖
  • javascript当中div在单行(float:left)用法

    div在单行(float:left) 例 1.2.1 divInOneLineIEFF.html <div style="width:100px"> ...

    马克java社区
  • CSS单位em和rem

    写过样式的都知道CSS是有单位的,想要写出还原设计稿的完美样式,离不开好的单位。现在CSS的单位有%、in、cm、mm、em、ex、pt、pc、px等原生单位,...

    wade
  • 网页结构与表现原则

    网页的结构与表现原则总的来说为: 先按结构和语义编写代码 然后进行CSS样式设置 减少HTML与CSS契合度(精简页面结构) 我们可以通过一个微博用户发言信息列...

    就只是小茗
  • css 使元素居中

    <div style="text-align:center;">居中显示</div>

    lin_zone

扫码关注云+社区

领取腾讯云代金券