Python爬虫:现学现用xpath爬取豆瓣音乐
爬虫的抓取方式有好几种,正则表达式,Lxml(xpath)与BeautifulSoup,我在网上查了一下资料,了解到三者之间的使用难度与性能
三种爬虫方式的对比。
这样一比较我我选择了Lxml(xpath)的方式了,虽然有三种方式,但肯定是要选择最好的方式来爬虫,这个道理大家都懂,另外有兴趣的朋友也可以去了解另外两种爬虫方式!
好了现在来讲讲xpath
由于Xpath属于lxml模块,所以首先需要安装lxml库,老办法直接在file-->setting---project interpreter 一键添加lxml库。
xpath简单用法
from lxml import etree
s=etree.HTML(源码) #将源码转化为能被XPath匹配的格式
s.xpath(xpath表达式) #返回为一列表,
基础语法:
// 双斜杠 定位根节点,会对全文进行扫描,在文档中选取所有符合条件的内容,以列表的形式返回。
/ 单斜杠 寻找当前标签路径的下一层路径标签或者对当前路标签内容进行操作
/text() 获取当前路径下的文本内容
/@xxxx 提取当前路径下标签的属性值
| 可选符 使用|可选取若干个路径 如//p | //div 即在当前路径下选取所有符合条件的p标签和div标签。
. 点 用来选取当前节点
.. 双点 选取当前节点的父节点
学以致用,方能让我们能快速掌握xpath语法功能。
我们这次需要爬取豆瓣音乐前250条
打开豆瓣音乐:https://music.douban.com/top250
获取单条数据
1.获取音乐标题
打开网址,按下F12,然后查找标题,右键弹出菜单栏 Copy==> Copy Xpath
这里我们想获取音乐标题,音乐标题的xpath是:xpath://*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div/a
# coding:utf-8
from lxml import etree
import requests url = 'https://music.douban.com/top250' html = requests.get(url).text #这里一般先打印一下html内容,看看是否有内容再继续。
s = etree.HTML(html)
title = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div/a')
print title
运行代码:
居然是空的。!!!
这里需要注意一下,浏览器复制的xpath只能作参考,因为浏览器经常会在自己里面增加多余的tbody标签,我们需要手动把这个标签删除
删除中间的/tbody后,是这样的,title = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/a')
然后我们再运行代码。
得到:<Element a at 0x53d26c8>
说明标题被获取到了。
因为要获取标题文本,所以xpath表达式要追加/text()title = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/a/text()')#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
又因为这个s.xpath返回的是一个集合,且集合中只有一个元素所以我再追加一个[0]
新的表达式:title = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/a/text()')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text(),再追加[0]
重新运行得到结果:
We Sing. We Dance. We Steal Things.
正是我们想要的标题。
2.获取音乐评分与评价人数
老办法,先用右键copy评分的xpath ://*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div/div/span[2]
复制评价人数的xpath://*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div/div/span[3]/text()
同样的我们要把tbody去掉,然后重新运行代码:
# coding:utf-8
from lxml import etree
import requests url = 'https://music.douban.com/top250' html = requests.get(url).text
s = etree.HTML(html)
title = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/a/text()')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
score = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/div/span[2]/text()')[0]#因为要获取文本,所以我需要这个当前路径下的文本,所以使用/text()
numbers = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/div/span[3]/text()')[0]#因为要获取文本,所以我需要这个当前路径下的文本,所以使用/text()
print title,score,numbers
得到:
We Sing. We Dance. We Steal Things.
9.1
(
100395人评价
)
3.获取音乐链接
copy标题的xpath,://*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div/a
想获取音乐连接href这里需要,获取这个标签属于,/@xxx可以提取当前路径标签下的属性值//*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div/a/@href
代码:
# coding:utf-8
from lxml import etree
import requests url = 'https://music.douban.com/top250' html = requests.get(url).text
s = etree.HTML(html)
href = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/a/@href')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
title = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/a/text()')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
score = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/div/span[2]/text()')[0]#因为要获取文本,所以我需要这个当前路径下的文本,所以使用/text()
numbers = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/div/span[3]/text()')[0]#因为要获取文本,所以我需要这个当前路径下的文本,所以使用/text()
print href,title,score,numbers
运行代码得到:
https://music.douban.com/subject/2995812/
We Sing. We Dance. We Steal Things.
9.1
(
100395人评价
)
5.获取图片地址:
找到图片,复制他的xpath地址://*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[1]/a/img
运行代码:
# coding:utf-8
from lxml import etree
import requests url = 'https://music.douban.com/top250' html = requests.get(url).text
s = etree.HTML(html)
href = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/a/@href')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
title = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/a/text()')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
score = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/div/span[2]/text()')[0]#因为要获取文本,所以我需要这个当前路径下的文本,所以使用/text()
numbers = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/div/span[3]/text()')[0]#因为要获取文本,所以我需要这个当前路径下的文本,所以使用/text()
imgpath = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[1]/a/img/@src')[0]#因为要获取文本,所以我需要这个当前路径下的文本,所以使用/text()
print href,title,score,numbers,imgpath
老套路:
得到结果:
https://music.douban.com/subject/2995812/
We Sing. We Dance. We Steal Things.
9.1
(
100395人评价
)
https://img3.doubanio.com/spic/s2967252.jpg
但是这只是获取了一条数据,如果获取多条数据呢?
获取多条数据
我们再看第二条数据,第三条数据,第四条数据
得到他们的xpath:
# coding:utf-8
from lxml import etree
import requests url = 'https://music.douban.com/top250' html = requests.get(url).text
s = etree.HTML(html)
title = s.xpath('//*[@id="content"]/div/div[1]/div/table[1]/tr/td[2]/div/a/text()')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
title2 = s.xpath('//*[@id="content"]/div/div[1]/div/table[2]/tr/td[2]/div/a/text()')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
title3 = s.xpath('//*[@id="content"]/div/div[1]/div/table[3]/tr/td[2]/div/a/text()')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
title4 = s.xpath('//*[@id="content"]/div/div[1]/div/table[4]/tr/td[2]/div/a/text()')[0]#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text()
print title,title2,title3,title4
得到:
We Sing. We Dance. We Steal Things.
Viva La Vida
华丽的冒险
范特西
对比他们的xpath,发现只有table序号不一样,我们可以就去掉序号,得到通用的xpath信息:
运行代码:
# coding:utf-8
from lxml import etree
import requests url = 'https://music.douban.com/top250' html = requests.get(url).text
s = etree.HTML(html)
titles = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[2]/div/a/text()')#因为要获取标题,所以我需要这个当前路径下的文本,所以使用/text() for title in titles:
print title.strip()
得到:
We Sing. We Dance. We Steal Things.
Viva La Vida
华丽的冒险
范特西
後。青春期的詩
是时候
Lenka
Start from Here
旅行的意义
太阳
Once (Soundtrack)
Not Going Anywhere
American Idiot
OK
無與倫比的美麗
亲爱的...我还不知道
城市
O
Wake Me Up When September Ends
叶惠美
七里香
21
My Life Will...
寓言
你在烦恼什么
其它的信息如:链接地址,评分,评价人数都可以用同样的办法来获取,现在我同时获取多条数据,因为每页数据是25条,所以:
完整代码如下:
# coding:utf-8
from lxml import etree
import requests
url = 'https://music.douban.com/top250'
html = requests.get(url).text
s = etree.HTML(html)
hrefs = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[2]/div/a/@href')
titles = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[2]/div/a/text()')
scores = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[2]/div/div/span[2]/text()')
numbers = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[2]/div/div/span[3]/text()')
imgs = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[1]/a/img/@src')
for i in range(25):
print hrefs[i],titles[i],scores[i],numbers[i],imgs[i]
得到:
一大批数据了,我就不展示了。有兴趣可以直接copy代码运行.,注意你得装上lxml与requests库.
我们也发现了问题每一个xpath路径特别长,能不能精简一下呢?
5. 精简一下xpath路径
hrefs = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[2]/div/a/@href')
titles = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[2]/div/a/text()')
scores = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[2]/div/div/span[2]/text()')
numbers = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[2]/div/div/span[3]/text()')
imgs = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr/td[1]/a/img/@src')
观察发现获取几个关键字段的xpath前缀都是 //*[@id="content"]/div/div[1]/div/table/tr
那我能不能把这些东西提出来呢,让后面的不同的自己去追加,另外这样写也不用管每个页面到底有多少条数据,只管查就行了。所以代码做了一下精简。
url = 'https://music.douban.com/top250' html = requests.get(url).text
s = etree.HTML(html)
trs = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr') #先提取tr之前的节点集合 for tr in trs: #遍历tr
href = tr.xpath('./td[2]/div/a/@href')[0] #注意新节点是tr下的节点
title = tr.xpath('./td[2]/div/a/text()')[0]
score = tr.xpath('./td[2]/div/div/span[2]/text()')[0]
number = tr.xpath('./td[2]/div/div/span[3]/text()')[0]
img = tr.xpath('./td[1]/a/img/@src')[0]
print href,title,score,number,img
得到的结果和之前是一样的。
但是,但是,这只是一个页面的数据,我现在想爬取多个页面的数据,怎么办呢?
获取个多页面数据.
观察一下翻页路径:
https://music.douban.com/top250?start=0
https://music.douban.com/top250?start=25
https://music.douban.com/top250?start=50
有没有发现页面只是后面start参数发生了改变,且增长为每次25,并且250条数据正好是10页。
所以我可以遍历这个页面。
代码:
for i in range(10):
url = 'https://music.douban.com/top250?start={}'.format(i*25)
print url
得到:
https://music.douban.com/top250?start=0
https://music.douban.com/top250?start=25
https://music.douban.com/top250?start=50
https://music.douban.com/top250?start=75
https://music.douban.com/top250?start=100
https://music.douban.com/top250?start=125
https://music.douban.com/top250?start=150
https://music.douban.com/top250?start=175
https://music.douban.com/top250?start=200
https://music.douban.com/top250?start=225
正是自己要的结果。
好了最后我们把代码拼装在一起,并注意每个方法的用途。
完整代码
# coding:utf-8
from lxml import etree
import requests #获取页面地址
def getUrl():
for i in range(10):
url = 'https://music.douban.com/top250?start={}'.format(i*25)
scrapyPage(url) #爬取每页数据
def scrapyPage(url):
html = requests.get(url).text
s = etree.HTML(html)
trs = s.xpath('//*[@id="content"]/div/div[1]/div/table/tr') for tr in trs:
href = tr.xpath('./td[2]/div/a/@href')[0]
title = tr.xpath('./td[2]/div/a/text()')[0]
score = tr.xpath('./td[2]/div/div/span[2]/text()')[0]
number = tr.xpath('./td[2]/div/div/span[3]/text()')[0]
img = tr.xpath('./td[1]/a/img/@src')[0]
print href, title, score, number, img if '__main__':
getUrl()
Python爬虫:现学现用xpath爬取豆瓣音乐的更多相关文章
- Python爬虫小白入门(七)爬取豆瓣音乐top250
抓取目标: 豆瓣音乐top250的歌名.作者(专辑).评分和歌曲链接 使用工具: requests + lxml + xpath. 我认为这种工具组合是最适合初学者的,requests比pytho ...
- 爬虫系列1:Requests+Xpath 爬取豆瓣电影TOP
爬虫1:Requests+Xpath 爬取豆瓣电影TOP [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]: ...
- 爬虫系列4:Requests+Xpath 爬取动态数据
爬虫系列4:Requests+Xpath 爬取动态数据 [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]:参 ...
- Python爬虫教程-13-爬虫使用cookie爬取登录后的页面(人人网)(下)
Python爬虫教程-13-爬虫使用cookie爬取登录后的页面(下) 自动使用cookie的方法,告别手动拷贝cookie http模块包含一些关于cookie的模块,通过他们我们可以自动的使用co ...
- 爬虫系列(十) 用requests和xpath爬取豆瓣电影
这篇文章我们将使用 requests 和 xpath 爬取豆瓣电影 Top250,下面先贴上最终的效果图: 1.网页分析 (1)分析 URL 规律 我们首先使用 Chrome 浏览器打开 豆瓣电影 T ...
- 爬虫系列(十一) 用requests和xpath爬取豆瓣电影评论
这篇文章,我们继续利用 requests 和 xpath 爬取豆瓣电影的短评,下面还是先贴上效果图: 1.网页分析 (1)翻页 我们还是使用 Chrome 浏览器打开豆瓣电影中某一部电影的评论进行分析 ...
- [Python爬虫] 使用 Beautiful Soup 4 快速爬取所需的网页信息
[Python爬虫] 使用 Beautiful Soup 4 快速爬取所需的网页信息 2018-07-21 23:53:02 larger5 阅读数 4123更多 分类专栏: 网络爬虫 版权声明: ...
- scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250
scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250 前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大 ...
- python定时器爬取豆瓣音乐Top榜歌名
python定时器爬取豆瓣音乐Top榜歌名 作者:vpoet mail:vpoet_sir@163.com 注:这些小demo都是前段时间为了学python写的,现在贴出来纯粹是为了和大家分享一下 # ...
随机推荐
- (尚029)Vue_案例_交互footer组件功能
需要实现界面截图: 难点分析:sAllCheck必须定义为计算属性 1.想到问题: 一旦写一个组件,需要接收哪些属性?? 因为只有属性确定了,标签才好写 todos属性可以确定三个方面的显示 2.做交 ...
- OKR案例——不同类型的OKR实例
OKR是一种能将团队调动起来一起向着一个方向去努力的绝佳目标管理法,它让我们的团队去挑战自己的极限,去实现更大的价值,去将我们的战略最完美的转化为成果. 然而,想要让OKR在我们的团队中发挥作用,制定 ...
- datetime.now()提示没有now方法
py3.6 导入方法是 from datetime import datetime 在使用datetime.now()的时候报错,说没有now 在保存module的create_time字段的时候,提 ...
- Vuejs基本使用
一.简单使用 ①首先需要实例化vue:new 出来,注意Vue大小写 ②通过el绑定元素:el 选项的作用就是告诉 Vue 管理模板的入口节点(不要绑定body和html) ③data:是响应式数据, ...
- 测试winform自动悬浮
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...
- Struts2工作原理和核心文件
一.Struts2工作原理 如下图: 二.Struts2配置文件 1.web.xml 任何MVC框架都需要与Web应用整合,这就不得不借助于web.xml文件,只有配置了web.xml文件的Servl ...
- PostgreSQL DISTINCT 和 DISTINCT ON
select语句中,使用distinct关键字,在处理select list后,结果表可以选择消除重复的行.在SELECT之后直接写入DISTINCT关键字以指定此关键字: SELECT DISTIN ...
- Oracle系列十五 控制用户权限
权限 数据库安全性 --系统安全性 --数据安全性 系统权限: 对于数据库的权限 对象权限: 操作数据库对象的权限 系统权限 超过一百多种有效的权限 数据库管理员具有高级权限以完成管理任务,例如: 创 ...
- 解决mysql的in条件中参数是带引号的字符串的时候查询失效
原文链接:https://blog.csdn.net/u014520745/article/details/54091256
- Python3基础 内置函数 eval str转为list tuple dict
Python : 3.7.3 OS : Ubuntu 18.04.2 LTS IDE : pycharm-community-2019.1.3 ...