前言
继续上一章的学习笔记,scrapy中常用到的两种抓取数据的方式,一个是CSS选择器,一个是XPATH选择器。而本章先介绍其中之一,xpath选择器。
music:
Xpath
什么是xpath?
XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。
xpath节点关系
现在有一段代码(伯乐在线的):
节点的概念
所谓的节点,就是向上面代码所看到的,像<head>,<title>,<meta>这样的标签..
而诸多标签形成了如下的关系:
- 父节点
- 子节点
- 同胞节点
- 先辈节点
- 后代节点
① 父节点:head就是title的父节点
②子节点:title就是head的子节点
③同胞节点:head下,有两个同级的meta节点,而这两个meta就是同胞节点
④先辈节点:head就是title的父节点,也是title的先辈节点,而html又是head的父节点,所以html也是title的先辈节点。
⑤后代节点:与先辈节点相反,也就是子孙节点,都可以认为是后代节点,比如html下的head,title节点,都是后代节点。
属性的概念
在说明之前,要明白一个词属性
:
<input id = "article" name = "article" />
这里的id,name
就是属性,而article是他们的值。
xpath语法
有了上面的概念,接下来就可以了解xpath表达式的语法了,假设我们有一个名为article的元素节点:
表达式 | 说明 |
---|---|
article | 选取所有 article元素的所有子节点 |
/article | 选取根元素(在页面上,根元素一般是html节点 )article |
article/a | 选取所有属于article的子元素(一定是子元素) 的a元素 |
//div | 选取所有(html里的 )div子元素(不论出现在文档的任何地方 ) |
article//div | 选取所有属于article元素的后代的 div元素,不管它出现在article之下的任何地方 |
//@class | 选取所有名为class 的属性(@代表某个元素的class属性 ) |
//span|//ul | 选取文档中的span和ul元素(|代表并集,和 ) |
xpath语法 - 谓语
表达式 | 说明 |
---|---|
/article/div[1] | 选取属于article子元素 的第一个div元素(写法:div[1] ) |
/article/div[last()] | 选取属于article子元素 的最后一个div元素(写法:div[last() ) |
/article/div[last()-1] | 选取属于article子元素 的倒数第二个div元素(写法:div[last()-1 ) |
//div[@lang] | 选取所有拥有lang属性的div 元素 |
//div[@lang=’eng’] | 选取所有拥有lang属性的为eng 的div元素 (***重要常用***) |
scrapy中的用法
打开伯乐在线首页,我们可以发现有一处拥有所有文章地址:
http://blog.jobbole.com/all-posts/
先抽取任意一篇文章进行分析,分析伯乐在线的html代码,抓取我们需要的信息:标题、时间、点赞数、收藏数。。。等等
以标题为例子:
linus定义linux
可以看到此处的div的class属性值为entry-header,此时可以如下写到:
class JobboleSpider(scrapy.Spider):
name = 'jobbole'
allowed_domains = ['blog.jobbole.com']
# start_urls = ['http://blog.jobbole.com/']
start_urls = ['http://blog.jobbole.com/all-posts/']
def parse(self, response):
"""
response是scrapy服务端响应的对象,调用extract方法可以提取
对应xpath响应的列表,但是提取第一个元素可以用[0],有一点弊端:
用[0],若不存在第一个元素则会报错,在css选择器中会总结另一种提
取方法....
"""
# 标题
article_title = response.xpath('//div[@class="entry-header"]/h1/text()').extract()[0]
在抓取伯乐实战中,scrapy用到的代码如下:
""" -------------- xpath 案例 start --------------"""
# 标题
article_title = response.xpath('//div[@class="entry-header"]/h1/text()').extract()[0]
print(article_title)
# 时间
article_time = response.xpath('//p[@class="entry-meta-hide-on-mobile"]/text()').extract()[0].strip().replace(
'·', '').strip()
print(article_time)
# 点赞数
article_praise = response.xpath('//span[contains(@class,"vote-post-up")]/h10/text()').extract()[0]
print(article_praise)
# 收藏数
bookmark = response.xpath('//span[contains(@class,"bookmark-btn")]/text()').extract()[0]
# 正则提取收藏数字
match_bookmark = re.match('.*(\d+).*', bookmark)
if match_bookmark:
article_bookmark = match_bookmark.group(1)
print(article_bookmark)
# 评论数
comments = response.xpath('//a[@href="#article-comment"]/text()').extract()[0]
match_comments = re.match('.*(\d+).*', comments)
if match_comments:
article_comments = match_comments.group(1)
print(article_comments)
# 文章详情
article_contents = response.xpath('//div[@class="entry"]').extract()[0]
# 文章标签
tag_list = response.xpath('//p[@class="entry-meta-hide-on-mobile"]/a/text()').extract()
# 去重标签
tag_list = [element for element in tag_list if not element.strip().endswith("评论")]
tags = ','.join(tag_list)
print(tags)
"""-------------- xpath 案例 end --------------"""
心得与tips
现在的浏览器都很强大,因为像谷歌,火狐这类浏览器自带了html的css和xpath复制功能,只需要F12打开开发者模式,然后选择你需要的标签属性,右键copy,便有各种css(cpoy selector
)或者xpath(copy xpath
)的选项,如下图:
当然,了解xpath语法对于我们学习来说是一件好事儿,毕竟熟能生巧,万一有一天遇到了像IE这样的浏览器,真的要哭了,因为楼主自己亲身体验过。。也正是因为IE没有这么强大的copy as功能,才对xpath略有了一丝熟悉。。
今日总结就到这里了,下一篇总结css选择器的使用。。!