【个人】爬虫实践,利用xpath方式爬取数据之爬取虾米音乐排行榜

本文主要是介绍【个人】爬虫实践,利用xpath方式爬取数据之爬取虾米音乐排行榜,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实验网站:虾米音乐排行榜
网站地址: http://www.xiami.com/chart 
难度系数:★☆☆☆☆
依赖库:request、lxml的etree (安装lxml:pip install lxml)
IDEA开发工具:PyCharm_2017.3
Python版本:Python3
期望结果:爬取出排行版歌名以及对应歌手

运行效果图:
音乐排行榜:
爬取数据结果图:

像这种简单的爬取就没必要使用Scrapy框架进行处理,是在有点大材小用,不过如果你刚开始学Scrapy的话,拿这些简单的练手是必须的,从简单的开始,慢慢去熟悉、掌握Scrapy框架。用BeautifulSoup也可以,简单实用,尤其元素选择器方面和Jquery很类似,上手比较快,但是最近我还是感觉XPath比较好用,所以今天就用XPath方式对数据进行提取吧。不过为了分享更多内容,让初学者少踩坑,快进步,我打算把这个实验再用Scrapy实现一遍,对于老鸟来说这实在没多大意义,但是对于初学者来说却能更好的理清思路,少走弯路。
这篇入门教程和未来Scrapy爬取虾米音乐排行榜的教程我都会以最简单直白的方式进行说明,基本从第一句代码开始写起,期间对遇到的问题进行分析、解决、对代码逐步完善,同时辅之更清晰明了的截图,让各位初学者更直观的看到代码逐步完善的过程,更好的理清思路。
首先用浏览器(推荐Chrome内核的浏览器,例如谷歌Chrome浏览器,Cent百分浏览器,此处用的Cent浏览器,感觉比Chrome更好用)打开网站  http://www.xiami.com/chart  ,基本就是我们看到的这样:
我们此时先试着写简单的代码,我们一步一步处理,遇到问题去解决:
import requests
from lxml import etreeurl_ = "http://www.xiami.com/chart"
page_source = requests.get(url=url_)
print("响应结果:\n",page_source.text)
model = etree.HTML(page_source.text)
以上代码就是最简单的获取网页源码的方式,我们运行发现好像没有达到我们的预期结果:
出现了400错误,什么问题呢?下面蓝色区域画出来的部分已经很明确的说明了,因为我们浏览器发送的请求服务端无法识别,仔细一想浏览器打开这个网址正常,而我们通过代码则不行,很明显就是Use-Agent(UA)不匹配了,找到问题原因就好办了,我们可以模拟一个UA,例如:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87,接着我们修改一下代码:
 1 import requests
 2 
 3 from lxml import etree
 4 
 5 
 6 url_ = "http://www.xiami.com/chart"
 7 
 8 headers_ = {
 9 
10     'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87'
11 
12 }
13 
14 page_source = requests.get(url=url_,headers=headers_)
15 
16 print("响应结果:\n",page_source.text)
17 
18 model = etree.HTML(page_source.text)
可以看到此时网站已经正确响应了,我们拿到了我们的“理想数据“,但仔细看了看响应的数据,然后搜索了一下,发现好像没有看到某首歌曲
的信息,也就是说目前返回的数据并不包含歌曲排行榜数据:
我明明是打开的这个  http://www.xiami.com/chart 网址啊,而且用浏览器打开后也加载出音乐排行榜的歌曲了啊,为什么返回的网页源码中找不到歌曲信息呢?不知道你发现没有,当浏览器打开这个网址时,页面中间区域排行榜数据处于一个正在加载中状态,并不是一下子整个页面出来的(你网速好可以忽略了...)
就类似于上图这样,一部分页面出来了而一部分还未加载完成,这时候你是不是就想到了Ajax异步加载了?这就对了,这块数据是Ajax后期加载出来的,是有一个新请求的,直接通过代码获取网页源码肯定不会得到期望结果的,我们应该想办法知道Ajax通过什么方式请求了哪个地址以及得到了什么类型的结果,于是乎浏览器的开发者工具就派上用场了:
我们可以看到当我们打开这个页面时都进行了右侧的请求响应处理,我们响应的Ajax请求肯定就在其中了,我们可以慢慢找,不过我们知道是Ajax请求了,那我们直接过滤“XHR”:
进过过滤我们发现就这一个请求,然后看了一下Response,最后确认就是它了!!
歌曲就在其中了,于是我们确定这就是我们最终要请求的URL了,然后我们再看一下该请求的相关信息:
于是我们知道了URL是: http://www.xiami.com/chart/data?c=103&type=0&page=1&limit=100&_=1517477892257  请求方式是:GET方式 等信息,那我们就接着修改代码吧:
(URL的请求参数,比如page、limit等我们就不细究了,一看就知道当前页码和每页返回数据大小)
import requests
from lxml import etreeurl_ = "http://www.xiami.com/chart/data?c=103&type=0&page=1&limit=100&_=1517477892257"headers_ = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87'}
page_source = requests.get(url=url_,headers=headers_)print("响应结果:\n",page_source.text)model = etree.HTML(page_source.text)
运行之后:
可以看到这就是我们理想数据了,相关音乐排行榜数据都在其中了,剩下的就是提取数据了,这里我们使用XPath语法提取,首先还是在浏览器那边定位一下我们想要的歌曲名、歌手所在元素位置,然后确定XPath路径写法。
我们看到歌曲名在<a>标签里面,而且这个标签是在样式类型为“info”的div标签里面嵌套的,层次为:
<div class="info"><p><strong><a>歌曲名等信息  在第一个p标签里面</a></strong></p><p>......</p>
</div>
那我们根据这个层级初步写出一个XPath路径:
//div[@class="info"]/p[1]/strong/a/text()    
我们使用XPath Helper插件进行验证一下:
    我们发现这句XPath选择是可以把当前页面所有的歌曲名称选择出来的,然后就是再选择歌曲对应的歌手,我们再看一下歌手标签所在的DOM结构:
我们看到歌曲名在<a>标签里面,而且这个标签是在样式类型为“info”的div标签里面嵌套的,层次为:
<div class="info"><p>......</p><p><a>歌手名称,在第二个p标签里面</a></p>
基于以上结构,我们初步下一个XPath路径:
//div[@class="info"]/p[2]/a
我们使用XPath Helper插件进行验证一下:
此时我们发现这个XPath选择确实把歌手名称选中了,但是好像有个问题,明明查询出来100首歌曲,怎么却有129位歌手呢?对应不起来啊。别急,那我们就仔细看一下每一首歌曲的歌手吧
从中发现,一首歌曲可能有多位演唱者,每一位演唱者占用一个<a>标签,且用“;”分隔,如下:
这样的话我们改进一下XPath选择,试试选择<a>标签所在的p标签,这样把多位歌手(即多个a标签)看成一个list集合,我们在Python代码处理即可,修改后的XPath选择如下:
//div[@class='info']/p[2]
此时我们看到这次选择的就不是每一位歌手所在a标签了,二是上一级的整个p标签,而且选择出来的歌手一共100位,正好和歌曲个数对应起来了,那么就到此为止,我们用代码处理:
import requests
from lxml import etreeurl_ = "http://www.xiami.com/chart/data?c=103&type=0&page=1&limit=100&_=1517477892257"headers_ = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87'
}page_source = requests.get(url=url_, headers=headers_)
print("响应结果:\n", page_source.text)
model = etree.HTML(page_source.text)
songs_list = model.xpath('//div[@class="info"]/p[1]/strong/a/text()')songer = model.xpath("//div[@class='info']/p[2]")
print("歌曲个数:{}   歌手个数:{}".format(len(songs_list),len(songer)))

 


运行结果:
对代码继续进行处理完善:
import requests
from lxml import etree
url_ = "http://www.xiami.com/chart/data?c=103&type=0&page=1&limit=100&_=1517477892257"headers_ = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87'
}
page_source = requests.get(url=url_, headers=headers_)print("响应结果:\n", page_source.text)model = etree.HTML(page_source.text)
songs_list = model.xpath('//div[@class="info"]/p[1]/strong/a/text()')
songer = model.xpath("//div[@class='info']/p[2]")
print("歌曲个数:{}   歌手个数:{}".format(len(songs_list), len(songer)))
for index, item in enumerate(songs_list):# 继续处理一首歌曲有多位演唱者的情况,因为每一位演唱者都在一个a标签里面,我们把多个a标签看成一个list集合处理songer_list = songer[index].xpath(".//a/text()")# 每一首歌曲的每一位演唱者组成一个list集合,我们利用join方法对list集合的每一项进行拼接,组成一个字符串结果dealed_songer = ",".join(songer_list)# 最后按格式输出结果print("{}、{}\t【{}】".format(index + 1, item, dealed_songer))

 


最终结果:
歌曲个数:100   歌手个数:100
1、Bad Boy    【Red Velvet(레드벨벳)】
2、Electric Kiss    【EXO(엑소)】
3、Cosmic Railway    【EXO(엑소)】
4、说散就散    【袁娅维(Tia)】
5、追光者    【岑宁儿】
6、我们不一样    【大壮】
7、带你去旅行    【校长(张驰)】
8、刚好遇见你    【李玉刚】
9、123我爱你    【新乐尘符】
10、空空如也    【胡66】
11、成都    【赵雷(雷子)】
12、红昭愿    【音阙诗听(Interseting)】
13、等你下课    【周杰伦,杨瑞代】
14、9420    【麦小兜】
15、Ei Ei    【偶像练习生】
16、广东爱情故事    【广东雨神】
17、小幸运    【田馥甄】
18、九张机    【叶炫清】
19、岁月神偷    【金玟岐】
20、BINGBIAN病变 (女声版)    【鞠文娴】
21、你就不要想起我    【田馥甄(Hebe)】
22、最美情侣    【白小白】
23、全部都是你    【Dragon Pig,Cloud Wang】
24、告白气球    【周杰伦(Jay Chou)】
25、사랑을 했다    【iKON(TEAM B)】
26、过往    【邹施如】
27、文爱    【CG(CHIGGA GANG黄鬼帮)】
28、差一步    【大壮】
29、在人间    【王建房】
30、Panama    【Matteo】
31、没有你陪伴真的好孤单    【梦然】
32、童话镇    【陈一发儿(陈一发)】
33、尽头    【音阙诗听(Interseting)】
34、Lovin’ You Mo’    【EXO(엑소)】
35、勉为其难    【王冕】
36、最美的期待    【周笔畅(BiBi Chou)】
37、非酋    【薛明媛,朱贺】
38、平凡之路    【朴树】
39、多幸运    【韩安旭】
40、再也没有    【Ryan.B,AY杨佬叁】
41、说散就散    【冯提莫(Ti mo Feng)】
42、空空如也    【任然】
43、Faded    【Alan Walker,Iselin Solheim】
44、你曾是少年    【S.H.E(SHE)】
45、小半    【陈粒(粒粒)】
46、All Right    【Red Velvet(레드벨벳)】
47、春风吹    【阿冷】
48、Shape of You    【Ed Sheeran(艾德·希兰)】
49、默    【那英】
50、喜欢你    【G.E.M.邓紫棋(邓紫棋)】
51、盗心贼    【黑龙】
52、演员 (Live)    【薛之谦】
53、恋人心    【魏新雨】
54、Please Don't Go    【Joel Adams】
55、其实都没有    【杨宗纬(Aska Yang)】
56、过客    【阿涵(周思涵)】
57、我们    【杨清柠,王乐乐】
58、丑八怪 (Live)    【薛之谦】
59、最久的瞬间    【炎亚纶(Aaron)】
60、大鱼    【周深(卡布叻)】
61、Time    【MKJ】
62、回忆总想哭    【南宫嘉骏,姜玉阳】
63、Despacito (Remix)    【Luis Fonsi,Daddy Yankee,Justin Bieber】
64、山丘    【李宗盛(Jonathan Lee)】
65、回忆那么伤    【孙子涵(Niko)】
66、后来的我们    【五月天(Mayday)】
67、一笑倾城    【汪苏泷】
68、陪你度过漫长岁月    【陈奕迅(Eason Chan)】
69、林中鸟    【葛林】
70、半壶纱    【刘珂矣】
71、生活不止眼前的苟且    【许巍】
72、给我一个理由忘记    【A-Lin(黄丽玲)】
73、光年之外    【G.E.M.邓紫棋(邓紫棋)】
74、Dream It Possible    【Delacey】
75、Sugar    【Maroon 5(魔力红)】
76、Havana    【Camila Cabello,Young Thug】
77、如果我们不曾相遇    【五月天(Mayday)】
78、全世界谁倾听你    【林宥嘉(Yoga Lin)】
79、短发    【LAMPHO(lampho猴子)】
80、退    【蒋蒋(蒋家驹)】
81、小公主    【蒋蒋,杨清柠】
82、奇妙能力歌    【陈粒(粒粒)】
83、雨后人去楼也空    【王乐乐】
84、歌在飞    【苏勒亚其其格(格格)】
85、我要你    【任素汐】
86、后会无期    【G.E.M.邓紫棋(邓紫棋)】
87、Зая    【Бамбинтон】
88、微微一笑很倾城    【杨洋】
89、Psycho (Pt. 2)    【Russ】
90、闪光 (Shinin’)    【钟铉(종현)】
91、四年半    【杨清柠】
92、情话微甜    【王圣锋,李朝】
93、愿得一人心    【李行亮】
94、病变remix    【前男友】
95、爱的就是你    【十二星宿风之少年,刘佳】
96、Grandpa    【阿克江LilAkin,Bohan Phoenix,Lofimaker】
97、好好 (想把你写成一首歌)    【五月天(Mayday)】
98、无问西东    【王菲(Faye Wong)】
99、理想三旬    【陈鸿宇】
100、走在冷风中    【刘思涵(Koala)】

    至此,本教程结束,通过本教程,你清晰的看到了这个简单数据爬取是怎么一步一步完成的,见证了从需求明确、问题原因分析、问题解决、代码完善、最终完成的整个生命周期,那么此时你也就对爬虫编写基本思路有了一个简单的认识,爬取数据的代码都不会太复杂,复杂就复杂在发现问题、解决问题方式的寻找中,好的爬虫在于数据价值、涵盖范围以及相关算法确定中。当然了,本教程爬取的数据没多大价值,仅仅是抛砖引玉而已,希望各位灵活运用。

 

转载于:https://www.cnblogs.com/geekworld/p/8410751.html

这篇关于【个人】爬虫实践,利用xpath方式爬取数据之爬取虾米音乐排行榜的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/551450

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X

pandas数据过滤

Pandas 数据过滤方法 Pandas 提供了多种方法来过滤数据,可以根据不同的条件进行筛选。以下是一些常见的 Pandas 数据过滤方法,结合实例进行讲解,希望能帮你快速理解。 1. 基于条件筛选行 可以使用布尔索引来根据条件过滤行。 import pandas as pd# 创建示例数据data = {'Name': ['Alice', 'Bob', 'Charlie', 'Dav