实验网站:虾米音乐排行榜
难度系数:★☆☆☆☆
依赖库: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 etree url_ = "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,接着我们修改一下代码:

 import requests

 from lxml import etree

 url_ = "http://www.xiami.com/chart"

 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)
 
    可以看到此时网站已经正确响应了,我们拿到了我们的“理想数据“,但仔细看了看响应的数据,然后搜索了一下,发现好像没有看到某首歌曲
的信息,也就是说目前返回的数据并不包含歌曲排行榜数据:
 
    我明明是打开的这个 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 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)
    运行之后:
    可以看到这就是我们理想数据了,相关音乐排行榜数据都在其中了,剩下的就是提取数据了,这里我们使用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 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)))
 
 
 
    运行结果:
    对代码继续进行处理完善:
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)】
 

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

【个人】爬虫实践,利用xpath方式爬取数据之爬取虾米音乐排行榜的更多相关文章

  1. 采用EaglePHP框架解决分布式集群服务器利用MEMCACHE方式共享SESSION数据的问题

    一.问题起源 稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网 站,用户系统是统一的,即一套用户名.密码在整个网站的各个模块中都是可以登录 ...

  2. 多域名THINKPHP利用MEMCACHE方式共享SESSION数据(转)

    一.问题起源 稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名.密码在整个网站的各个模块中都是可以登录使 ...

  3. Python爬虫实践~BeautifulSoup+urllib+Flask实现静态网页的爬取

    爬取的网站类型: 论坛类网站类型 涉及主要的第三方模块: BeautifulSoup:解析.遍历页面 urllib:处理URL请求 Flask:简易的WEB框架 介绍: 本次主要使用urllib获取网 ...

  4. MSSQL · 最佳实践 · 利用文件组实现冷热数据隔离备份方案

    文件组的基本知识点介绍完毕后,根据场景引入中的内容,我们将利用SQL Server文件组技术来实现冷热数据隔离备份的方案设计介绍如下. 设计分析 由于payment数据库过大,超过10TB,单次全量备 ...

  5. python利用xmlrpc方式对odoo数据表进行增删改查操作

    # -*- encoding: utf-8 -*- import xmlrpclib #导入xmlrpc库,这个库是python的标准库. username ='admin' #用户登录名 pwd = ...

  6. 分批次从musql取数据,每次取1000条

    $t = new Gettags(); $num=$t->sum_tag(); $num=$num/1000; $flag_num=ceil($num); $flag_array=array() ...

  7. 使用google chrome抓取数据:抓取全国的高中的数据

    http://tomycat.github.io/blog/other/2014/05/28/use-google-chrome-capture-data.html

  8. .NET抓取数据范例 抓取页面上所有的链接

    原文发布时间为:2009-11-15 -- 来源于本人的百度文章 [由搬家工具导入] .NET抓取数据范例 抓取页面上所有的链接 前台: <%@ Page Language="C#&q ...

  9. R中使用rvest爬取数据小试

    总结R中使用 xpath 和 css selectors 获取标签内容(xpath功能强大,而CSS选择器通常语法比较简洁,运行速度更快些) 例:抓取下面标签的内容: <h3 class=&qu ...

随机推荐

  1. 【转】JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)

    前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...

  2. 处理 Windows 虚拟机的计划内维护通知

    Azure 定期执行更新,以提高虚拟机的主机基础结构的可靠性.性能及安全性. 更新包括如下更改:修补托管环境或升级以及解除硬件授权. 大多数此类更新在执行时不会影响托管的虚拟机. 但是,也会存在更新产 ...

  3. 使用 Azure PowerShell 监视和更新 Windows 虚拟机

    Azure 监视使用代理从 Azure VM 收集启动和性能数据,将此数据存储在 Azure 存储中,并使其可供通过门户.Azure PowerShell 模块和 Azure CLI 进行访问. 使用 ...

  4. ping 命令 指定特定网卡 发送 ICMP 数据包

    Windows : ping -S Linux : ping -I <device> -I interface interface is either an address, or an ...

  5. vue2.0学习笔记之路由(二)路由嵌套

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. TML 打印预览问题,怎么设置有些内容不出现在打印预览页面上。怎么控制,有下代码 看得不是很懂 求解释

    HTML <style> 标签的 media 属性 HTML <style> 标签 实例 针对两种不同媒介类型的两种不同的样式(计算机屏幕和打印): <html> ...

  7. NOIP模拟赛-2018.10.22

    模拟赛 今天第一节课是历史,当然是不可能上的,一来到机房发现今天高二考试... 老师说以后可能还要给高一考...那还不如现在跟着做好了,毕竟在学长学姐中垫底显得没那么丢人 这套题风格挺奇怪的...为什 ...

  8. 【洛谷P3410】拍照题解(最大权闭合子图总结)

    题目描述 小B有n个下属,现小B要带着一些下属让别人拍照. 有m个人,每个人都愿意付给小B一定钱让n个人中的一些人进行合影.如果这一些人没带齐那么就不能拍照,小B也不会得到钱. 注意:带下属不是白带的 ...

  9. RMAN常用命令汇总!

    进入RMAN:$ rman target sys/oracle@orcl   --远程连接到rman$ rman target sys/oracle@orcl @backup_db.ram   --远 ...

  10. shiro实战系列(八)之安全管理器

    Apache Shiro 提供安全框架界独一无二的东西:一个完整的企业级 Session 解决方案,从最简单的命令行及智能手机 应用到最大的集群企业 Web 应用程序.   这对许多应用有着很大的影响 ...