Scrapy笔记04- Selector详解

在你爬取网页的时候,最普遍的事情就是在页面源码中提取需要的数据,我们有几个库可以帮你完成这个任务:

  1. BeautifulSoup是python中一个非常流行的抓取库, 它还能合理的处理错误格式的标签,但是有一个唯一缺点就是:它运行很慢。
  2. lxml是一个基于ElementTree的XML解析库(同时还能解析HTML), 不过lxml并不是Python标准库

而Scrapy实现了自己的数据提取机制,它们被称为选择器,通过XPathCSS表达式在HTML文档中来选择特定的部分

XPath是一用来在XML中选择节点的语言,同时可以用在HTML上面。 CSS是一种HTML文档上面的样式语言。

Scrapy选择器构建在lxml基础之上,所以可以保证速度和准确性。

本章我们来详细讲解下选择器的工作原理,还有它们极其简单和相似的API,比lxml的API少多了,因为lxml可以用于很多其他领域。

完整的API请查看Selector参考

关于选择器

Scrapy帮我们下载完页面后,我们怎样在满是html标签的内容中找到我们所需要的元素呢,这里就需要使用到选择器了,它们是用来定位元素并且提取元素的值。先来举几个例子看看:

  • /html/head/title: 选择<title>节点, 它位于html文档的<head>节点内
  • /html/head/title/text(): 选择上面的<title>节点的内容.
  • //td: 选择页面中所有的元素
  • //div[@class=”mine”]: 选择所有拥有属性class="mine"的div元素

Scrapy使用css和xpath选择器来定位元素,它有四个基本方法:

  • xpath(): 返回选择器列表,每个选择器代表使用xpath语法选择的节点
  • css(): 返回选择器列表,每个选择器代表使用css语法选择的节点
  • extract(): 返回被选择元素的unicode字符串
  • re(): 返回通过正则表达式提取的unicode字符串列表

使用选择器

下面我们通过Scrapy shell演示下选择器的使用,假设我们有如下的一个网页http://doc.scrapy.org/en/latest/_static/selectors-sample1.html,内容如下:

<html>
<head>
<base href='http://example.com/' />
<title>Example website</title>
</head>
<body>
<div id='images'>
<a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>
<a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>
<a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>
<a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>
<a href='image5.html'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>
</div>
</body>
</html>

首先我们打开shell

scrapy shell http://doc.scrapy.org/en/latest/_static/selectors-sample1.html

运行

>>> response.xpath('//title/text()')
[<Selector (text) xpath=//title/text()>]
>>> response.css('title::text')
[<Selector (text) xpath=//title/text()>]

结果可以看出,xpath()css()方法返回的是SelectorList实例,是一个选择器列表,你可以选择嵌套的数据:

>>> response.css('img').xpath('@src').extract()
[u'image1_thumb.jpg',
u'image2_thumb.jpg',
u'image3_thumb.jpg',
u'image4_thumb.jpg',
u'image5_thumb.jpg']

必须使用.extract()才能提取最终的数据,如果你只想获得第一个匹配的,可以使用.extract_first()

>>> response.xpath('//div[@id="images"]/a/text()').extract_first()
u'Name: My image 1 '

如果没有找到,会返回None,还可选择默认值

>>> response.xpath('//div[@id="not-exists"]/text()').extract_first(default='not-found')
'not-found'

而CSS选择器还可以使用CSS3标准:

>>> response.css('title::text').extract()
[u'Example website']

下面是几个比较全面的示例:

>>> response.xpath('//base/@href').extract()
[u'http://example.com/'] >>> response.css('base::attr(href)').extract()
[u'http://example.com/'] >>> response.xpath('//a[contains(@href, "image")]/@href').extract()
[u'image1.html',
u'image2.html',
u'image3.html',
u'image4.html',
u'image5.html'] >>> response.css('a[href*=image]::attr(href)').extract()
[u'image1.html',
u'image2.html',
u'image3.html',
u'image4.html',
u'image5.html'] >>> response.xpath('//a[contains(@href, "image")]/img/@src').extract()
[u'image1_thumb.jpg',
u'image2_thumb.jpg',
u'image3_thumb.jpg',
u'image4_thumb.jpg',
u'image5_thumb.jpg'] >>> response.css('a[href*=image] img::attr(src)').extract()
[u'image1_thumb.jpg',
u'image2_thumb.jpg',
u'image3_thumb.jpg',
u'image4_thumb.jpg',
u'image5_thumb.jpg']

嵌套选择器

xpath()css()返回的是选择器列表,所以你可以继续使用它们的方法。举例来讲:

>>> links = response.xpath('//a[contains(@href, "image")]')
>>> links.extract()
[u'<a href="image1.html">Name: My image 1 <br><img src="data:image1_thumb.jpg"></a>',
u'<a href="image2.html">Name: My image 2 <br><img src="data:image2_thumb.jpg"></a>',
u'<a href="image3.html">Name: My image 3 <br><img src="data:image3_thumb.jpg"></a>',
u'<a href="image4.html">Name: My image 4 <br><img src="data:image4_thumb.jpg"></a>',
u'<a href="image5.html">Name: My image 5 <br><img src="data:image5_thumb.jpg"></a>'] >>> for index, link in enumerate(links):
... args = (index, link.xpath('@href').extract(), link.xpath('img/@src').extract())
... print 'Link number %d points to url %s and image %s' % args Link number 0 points to url [u'image1.html'] and image [u'image1_thumb.jpg']
Link number 1 points to url [u'image2.html'] and image [u'image2_thumb.jpg']
Link number 2 points to url [u'image3.html'] and image [u'image3_thumb.jpg']
Link number 3 points to url [u'image4.html'] and image [u'image4_thumb.jpg']
Link number 4 points to url [u'image5.html'] and image [u'image5_thumb.jpg']

使用正则表达式

Selector有一个re()方法通过正则表达式提取数据,它返回的是unicode字符串列表,你不能再去嵌套使用

>>> response.xpath('//a[contains(@href, "image")]/text()').re(r'Name:\s*(.*)')
[u'My image 1',
u'My image 2',
u'My image 3',
u'My image 4',
u'My image 5'] >>> response.xpath('//a[contains(@href, "image")]/text()').re_first(r'Name:\s*(.*)')
u'My image 1'

XPath相对路径

当你嵌套使用XPath时候,不要使用/开头的,因为这个会相对文档根节点开始算起,需要使用相对路径

>>> divs = response.xpath('//div')
>>> for p in divs.xpath('.//p'): # extracts all <p> inside
... print p.extract() # 或者下面这个直接使用p也可以
>>> for p in divs.xpath('p'):
... print p.extract()

XPath建议

使用text作为条件时

避免使用.//text(),直接使用.

>>> sel.xpath("//a[contains(., 'Next Page')]").extract()
[u'<a href="#">Click here to go to the <strong>Next Page</strong></a>']

//node[1]和(//node)[1]区别

  • //node[1]: 选择所有位于第一个子节点位置的node节点
  • (//node)[1]: 选择所有的node节点,然后返回结果中的第一个node节点

通过class查找时优先考虑CSS

>> from scrapy import Selector
>>> sel = Selector(text='<div class="hero shout"><time datetime="2014-07-23 19:00">Special date</time></div>')
>>> sel.css('.shout').xpath('./time/@datetime').extract()
[u'2014-07-23 19:00']

Scrapy笔记04- Selector详解的更多相关文章

  1. expect学习笔记及实例详解【转】

    1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:1.1 首行加上/usr/bin/expect1.2 spawn: 后面加上需要执行的shell命令,比如说sp ...

  2. Java NIO 的前生今世 之四 NIO Selector 详解

    Selector Selector 允许一个单一的线程来操作多个 Channel. 如果我们的应用程序中使用了多个 Channel, 那么使用 Selector 很方便的实现这样的目的, 但是因为在一 ...

  3. Hive笔记--sql语法详解及JavaAPI

    Hive SQL 语法详解:http://blog.csdn.net/hguisu/article/details/7256833Hive SQL 学习笔记(常用):http://blog.sina. ...

  4. Docker技术入门与实战 第二版-学习笔记-3-Dockerfile 指令详解

    前面已经讲解了FROM.RUN指令,还提及了COPY.ADD,接下来学习其他的指令 5.Dockerfile 指令详解 1> COPY 复制文件 格式: COPY  <源路径> .. ...

  5. 算法笔记--sg函数详解及其模板

    算法笔记 参考资料:https://wenku.baidu.com/view/25540742a8956bec0975e3a8.html sg函数大神详解:http://blog.csdn.net/l ...

  6. Scrapy的Item_loader机制详解

    一.ItemLoader与Item的区别 ItemLoader是负责数据的收集.处理.填充,item仅仅是承载了数据本身 数据的收集.处理.填充归功于item loader中两个重要组件: 输入处理i ...

  7. Android笔记——四大组件详解与总结

     android四大组件分别为activity.service.content provider.broadcast receiver. ------------------------------- ...

  8. Struts2学习笔记(二)——配置详解

    1.Struts2配置文件加载顺序: default.properties(默认常量配置) struts-default.xml(默认配置文件,主要配置bean和拦截器) struts-plugin. ...

  9. Struts2学习笔记二 配置详解

    Struts2执行流程 1.简单执行流程,如下所示: 在浏览器输入请求地址,首先会被过滤器处理,然后查找主配置文件,然后根据地址栏中输入的/hello去每个package中查找为/hello的name ...

  10. vue.js学习笔记(二)——vue-router详解

    vue-router详解 原文链接:www.jianshu.com 一.前言 要学习vue-router就要先知道这里的路由是什么?为什么我们不能像原来一样直接用<a></a> ...

随机推荐

  1. HandlerInterceptorAdapter

    handler,是指controller的@Controller注解下的整个方法名

  2. IntelliJ IDEA 超实用使用技巧分享

    https://blog.csdn.net/weixin_38405253/article/details/102583954 知识点概览: 高效率配置 日常使用 必备快捷键(★★) 查找 跳转切换 ...

  3. ReentrantLock和Condition实现生产者和消费者

    一个生产者和一个消费者 public class ConditionTest { private static ReentrantLock lock = new ReentrantLock(); pr ...

  4. postgresql NUMERIC(precision, scale)

  5. R数据挖掘 第三篇:聚类的评估(簇数确定和轮廓系数)和可视化

    在实际的聚类应用中,通常使用k-均值和k-中心化算法来进行聚类分析,这两种算法都需要输入簇数,为了保证聚类的质量,应该首先确定最佳的簇数,并使用轮廓系数来评估聚类的结果. 一,k-均值法确定最佳的簇数 ...

  6. U9 DLL读取配制文件

    在网上大多数的例子都是如何访问程序运行的目录下的配制文件,但是U9BP里要将DLL放到生产环境,我并不知道生产环境运行的目录,所以只能DLL读取当前目录XML. 过下面几个方法都可以拿到程序所在的文件 ...

  7. JavaScript学习思维导图

    JS基本概念 JS操作符 JS基本语法 JS数组 JS Date用法 JS 字符串用法 JS编程风格 JS实践

  8. Python 绘图与可视化 matplotlib 动态条形图 bar

    bar的参考链接:https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.bar.html 第一种办法 一种方法是每次都重新画,包括清除f ...

  9. Java虚拟机内存区域详解

    JVM 运行时的数据区域 首先获取一个直观的认识: 总共也就这么 5 个区(直接内存不属于 JVM 运行时数据区的一部分),除了程序计数器其他的地方都有可能出现 OOM (OutOfMemoryErr ...

  10. 两道JVM面试题,竟让我回忆起了中学时代!

    作者:肥朝 原文链接:https://mp.weixin.qq.com/s/4wJ6ANal0blLOseasfIuVw 中学授课模式 考虑到可能有部分粉丝对JVM参数不清楚,所以我们参照中学的授课模 ...