[转]scrapy 选择器官方文档

当抓取网页时,常见的任务是从HTML源码中提取数据。现有的一些库可以达到这个目的:

  • BeautifulSoup
  • lxml

Scrapy 提取数据有自己的一套机制。它们被称作选择器(seletors),因为他们通过特定的 XPath 或者 CSS 表达式来“选择” HTML 文件中的某个部分。

构造选择器

Scrapy selector 是以 文字(Text)或 TextResponse 构造的 Selector。其根据输入类型自动选择最优的分析方法(XML vs HTML):

>>> from scrapy.selector import Selector
>>> from scrapy.http import HtmlResponse

以文字构造:

>>> body = ‘<html><body><span>good</span></body></html>‘
>>> Selector(text=body).xpath(‘//span/text()‘).extract()
[u‘good‘]

以 response 构造:

>>> response = HtmlResponse(url=‘http://example.com‘, body=body)
>>> Selector(response=response).xpath(‘//span/text()‘).extract()
[u‘good‘]

为了方便起见,response 对象以 .selector 属性提供了一个 selector:

>>> response.selector.xpath(‘//span/text()‘).extract()
[u‘good‘]

使用选择器

使用 Scrapy Shell 和 Scrapy 文档服务器的一个样例页面,来解释如何使用选择器:

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

当 shell 载入后,将获得名为 response 的 shell 变量,其为响应的 response,并且在其 response.selector 属性上绑定了一个 selector。

因为处理的是 HTML,选择器自动使用 HTML 语法分析。

那么,通过查看 HTML code 该页面的源码,可以构建一个 XPath 来选择 title 标签内的文字:

>>> response.selector.xpath(‘//title/text()‘)
[<Selector (text) xpath=//title/text()>]

由于在 response 中使用 XPath、CSS 查询十分普遍,因此,Scrapy 提供了两个实用的快捷方式:

response.xpath()

response.css()

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

.xpath() 以及 .css() 方法返回一个类 SelectList 的实例,它是一个新选择器的列表。这个 API 可以用来快速的提取嵌套数据。

为了提取真实的原文数据,需要调用 .extract() 方法如下:

>>> response.xpath(‘//title/text()‘).extract()
[u‘Example website‘]

CSS 选择器可以使用 CSS3 伪元素(pseudo-elements)来选择文字或者属性节点:

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

获取得到根 URL(base URL)和一些图片链接:

>>> 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() or css())返回相同类型的选择器列表,因此也可以对这些选择器调用选择器方法:

>>> links = response.xpath(‘//a[contains(@href, "image")]‘)
>>> links.extract()
[u‘<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>‘,
 u‘<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>‘,
 u‘<a href="image3.html">Name: My image 3 <br><img src="image3_thumb.jpg"></a>‘,
 u‘<a href="image4.html">Name: My image 4 <br><img src="image4_thumb.jpg"></a>‘,
 u‘<a href="image5.html">Name: My image 5 <br><img src="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() 方法,用来通过正则表达式来提取数据。然而,不同于使用 .xpath() 或者 .css() 方法,.re() 方法返回 Unicode 字符串的列表。所以无法构造嵌套式的 .re() 调用。

>>> 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‘]

使用相对 XPaths

如果使用嵌套的选择器,并且使用起始为 / 的 XPath, 那么该 XPath 将对文档使用绝对路径,而且对于你调用的 Selector 不是相对路径。

比如,假设要提取 <div> 元素中所有的 <p> 元素。首先,先得到所有的 <div> 元素:

>>> divs = response.xpath(‘//div‘)

开始时,你也许会尝试使用下面的错误的方法,因为它其实是从整篇文档中,而不是仅仅从那些 <div> 元素内部提取所有的 <p> 元素:

>>> for p in divs.xpath(‘//p‘):  # this is wrong - gets all <p> from the whole document
...     print p.extract()

下面是比较适合的处理方法(注意 .//p XPath的点前缀):

>>> for p in divs.xpath(‘.//p‘):  # extracts all <p> inside
...     print p.extract()

另一种常见的情况是提取所有直系的 <p> 元素:

>>> for p in divs.xpath(‘p‘):
...     print p.extract()

使用 EXSLT 扩展

因建于 lxml 之上,Scrapy 选择器也支持一些 EXSLT 扩展,可以在 XPath 表达式中使用这些预先指定的命名空间:

前缀 命名空间 用途
re http://exslt.org/regular-expressions 正则表达式
set http://exslt.org/sets 集合操作

正则表达式

例如在 XPath 的 starts-with() 或 contains() 无法满足需求时,test() 函数可以非常有用。

例如在列表中选择有 “class” 元素且结尾为一个数字的链接:

>>> from scrapy import Selector
>>> doc = """
... <div>
...     <ul>
...         <li class="item-0"><a href="link1.html">first item</a></li>
...         <li class="item-1"><a href="link2.html">second item</a></li>
...         <li class="item-inactive"><a href="link3.html">third item</a></li>
...         <li class="item-1"><a href="link4.html">fourth item</a></li>
...         <li class="item-0"><a href="link5.html">fifth item</a></li>
...     </ul>
... </div>
... """
>>> sel = Selector(text=doc, type="html")
>>> sel.xpath(‘//li//@href‘).extract()
[u‘link1.html‘, u‘link2.html‘, u‘link3.html‘, u‘link4.html‘, u‘link5.html‘]
>>> sel.xpath(‘//li[re:test(@class, "item-\d$")]//@href‘).extract()
[u‘link1.html‘, u‘link2.html‘, u‘link4.html‘, u‘link5.html‘]
>>>

警告:C 语言库 libxslt 不支持 EXSLT 正则表达式,因此 lxml 在实现时使用了 Python re 模块的钩子。因此,在 XPath 表达式中使用 regexp 函数可能会牺牲少量的性能。

集合操作

集合操作可以方便地用于在提取文字元素前从文档树种去除一些部分。

例如使用 itemscopes 组合对应的 itemprops 来提取微数据(来自 http://schema.org/Product 的样本内容)

>>> doc = """
... <div itemscope itemtype="http://schema.org/Product">
...   <span itemprop="name">Kenmore White 17" Microwave</span>
...   <img src="kenmore-microwave-17in.jpg" alt=‘Kenmore 17" Microwave‘ />
...   <div itemprop="aggregateRating"
...     itemscope itemtype="http://schema.org/AggregateRating">
...    Rated <span itemprop="ratingValue">3.5</span>/5
...    based on <span itemprop="reviewCount">11</span> customer reviews
...   </div>
...
...   <div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
...     <span itemprop="price">$55.00</span>
...     <link itemprop="availability" href="http://schema.org/InStock" />In stock
...   </div>
...
...   Product description:
...   <span itemprop="description">0.7 cubic feet countertop microwave.
...   Has six preset cooking categories and convenience features like
...   Add-A-Minute and Child Lock.</span>
...
...   Customer reviews:
...
...   <div itemprop="review" itemscope itemtype="http://schema.org/Review">
...     <span itemprop="name">Not a happy camper</span> -
...     by <span itemprop="author">Ellie</span>,
...     <meta itemprop="datePublished" content="2011-04-01">April 1, 2011
...     <div itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating">
...       <meta itemprop="worstRating" content = "1">
...       <span itemprop="ratingValue">1</span>/
...       <span itemprop="bestRating">5</span>stars
...     </div>
...     <span itemprop="description">The lamp burned out and now I have to replace
...     it. </span>
...   </div>
...
...   <div itemprop="review" itemscope itemtype="http://schema.org/Review">
...     <span itemprop="name">Value purchase</span> -
...     by <span itemprop="author">Lucas</span>,
...     <meta itemprop="datePublished" content="2011-03-25">March 25, 2011
...     <div itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating">
...       <meta itemprop="worstRating" content = "1"/>
...       <span itemprop="ratingValue">4</span>/
...       <span itemprop="bestRating">5</span>stars
...     </div>
...     <span itemprop="description">Great microwave for the price. It is small and
...     fits in my apartment.</span>
...   </div>
...   ...
... </div>
... """
>>>
>>> for scope in sel.xpath(‘//div[@itemscope]‘):
...     print "current scope:", scope.xpath(‘@itemtype‘).extract()
...     props = scope.xpath(‘‘‘
...                 set:difference(./descendant::*/@itemprop,
...                                .//*[@itemscope]/*/@itemprop)‘‘‘)
...     print "    properties:", props.extract()
...     print
...

current scope: [u‘http://schema.org/Product‘]
    properties: [u‘name‘, u‘aggregateRating‘, u‘offers‘, u‘description‘, u‘review‘, u‘review‘]

current scope: [u‘http://schema.org/AggregateRating‘]
    properties: [u‘ratingValue‘, u‘reviewCount‘]

current scope: [u‘http://schema.org/Offer‘]
    properties: [u‘price‘, u‘availability‘]

current scope: [u‘http://schema.org/Review‘]
    properties: [u‘name‘, u‘author‘, u‘datePublished‘, u‘reviewRating‘, u‘description‘]

current scope: [u‘http://schema.org/Rating‘]
    properties: [u‘worstRating‘, u‘ratingValue‘, u‘bestRating‘]

current scope: [u‘http://schema.org/Review‘]
    properties: [u‘name‘, u‘author‘, u‘datePublished‘, u‘reviewRating‘, u‘description‘]

current scope: [u‘http://schema.org/Rating‘]
    properties: [u‘worstRating‘, u‘ratingValue‘, u‘bestRating‘]

>>>

在这里,首先在 itemscope 元素上迭代,对于其中的每一个元素,我们寻找所有的 itemprops 元素,并排除那些身在另一个 itemscope 内的元素。

内建选择器的参考

class scrapy.selector.Selector(response=None, text=None, type=None)

Selector 的实例时对选择某些内容响应的封装。

response 是 HTMLResponse 或 XMLResponse 的一个对象,将被用来选择和提取数据。

text 是在 response 不可用时的一个 unicode 字符串或 utf-8 编码的文字。将 text 和 response 一起使用时未定义行为。

type 定义了选择器类型,可以是 html, xml 或 None(默认)。

如果 type 是 None,选择器会根据 response 类型(参见下面)自动选择最佳类型,或者在和 text 一起使用时,默认为 html。

如果 type 是None,并传递了一个 response,选择器类型将从 response 类型中推导如下:

  • "html" for HtmlResponse type
  • "xml" for XmlResponse type
  • "html" for anything else

其他情况下,如果设定了 type ,选择器类型将被强制设定,而不进行检测。

xpath(query)

寻找可以匹配 xpath query 的节点,并返回一个 SelectorList 的一个实例结果,单一化其所有元素。列表元素也实现了 Selector 的接口。

query 是包含 XPath 查询请求的字符串。

方便起见该方法也可以通过 response.xpath() 调用。

css(query)

css(query)

应用给定的 CSS 选择器,返回 SelectorList 的一个实例。

query是一个包含 CSS 选择器的字符串。

在后台,通过 cssselect 库和运行 .xpath() 方法,CSS 查询会被转换为 XPath 查询。

方便起见该方法也可以通过 response.css() 调用。

extract()

串行化并将匹配到的节点返回一个 unicode 字符串列表。 结尾是编码内容的百分比。

re(regex)

应用给定的 regex,并返回匹配到的 unicode 字符串列表。

regex可以是一个已编译的正则表达式,也可以是一个将被 re.compile(regex) 编译为正则表达式的字符串。

register_namespace(prefix, uri)

注册给定的命名空间,其将在 Selector 中使用。 不注册命名空间,你将无法从非标准命名空间中选择或提取数据。

remove_namespaces()

移除所有的命名空间,允许使用少量的命名空间 xpaths 遍历文档。参加下面的例子。

__nonzero__()

如果选择了任意的真实文档,将返回 True ,否则返回 False 。 也就是说, Selector 的布尔值是通过它选择的内容确定的。

SelectorList 对象

class scrapy.selector.SelectorList

SelectorList 类是内建 list 类的子类,提供了一些额外的方法。

xpath(query)

对列表中的每个元素调用.xpath()方法,返回结果为另一个单一化的 SelectorList。

query 和 Selector.xpath() 中的参数相同。

css(query)

对列表中的各个元素调用.css() 方法,返回结果为另一个单一化的 SelectorList。

query 和 Selector.css() 中的参数相同。

extract()

对列表中的各个元素调用.extract()方法,返回结果为单一化的 unicode 字符串列表。

re()

对列表中的各个元素调用 .re() 方法,返回结果为单一化的 unicode 字符串列表。

__nonzero__()

列表非空则返回 True,否则返回 False。

在 HTML 响应上的选择器样例

这里是一些 Selector 的样例,用来说明一些概念。在所有的例子中,假设已经有一个通过 HtmlResponse 对象实例化的 Selector,如下:

sel = Selector(html_response)

#从 HTML 响应主体中提取所有的<h1>元素,返回:class:Selector 对象(即 SelectorList 的一个对象)的列表:

sel.xpath("//h1")

#从 HTML 响应主体上提取所有<h1>元素的文字,返回一个 unicode 字符串的列表:

sel.xpath("//h1").extract()         # this includes the h1 tag
sel.xpath("//h1/text()").extract()  # this excludes the h1 tag

#在所有<p>标签上迭代,打印它们的类属性:

for node in sel.xpath("//p"):
    print node.xpath("@class").extract()

在 XML 响应上的选择器样例

这里是一些样例,用来说明一些概念。在两个例子中,我们假设已经有一个通过 XmlResponse 对象实例化的 Selector ,如下:

sel = Selector(xml_response)

#从 XML 响应主体中选择所有的 product 元素,返回 Selector 对象(即 SelectorList 对象)的列表:

sel.xpath("//product")

#从 Google Base XML feed 中提取所有的价钱,这需要注册一个命名空间:

sel.register_namespace("g", "http://base.google.com/ns/1.0")
sel.xpath("//g:price").extract()

移除命名空间

在处理爬虫项目时,完全去掉命名空间而仅仅处理元素名字,写更多简单/实用的 XPath 会方便很多。你可以为此实用 Selector.remove_namespaces() 方法。

以 Github 博客的 atom 订阅来解释这个情况:

$ scrapy shell https://github.com/blog.atom

一旦进入 shell,我们可以尝试选择所有的 <link> 对象,可以看到没有结果(因为 Atom XML 命名空间混淆了这些节点):

>>> response.xpath("//link")
[]

但一旦调用 Selector.remove_namespaces() 方法,所有节点都可以直接通过他们的名字来访问:

>>> response.selector.remove_namespaces()
>>> response.xpath("//link")
[<Selector xpath=‘//link‘ data=u‘<link xmlns="http://www.w3.org/2005/Atom‘>,
 <Selector xpath=‘//link‘ data=u‘<link xmlns="http://www.w3.org/2005/Atom‘>,
 ...

如果你对为什么命名空间移除操作并不总是被调用,而需要手动调用有疑惑。这是因为存在如下两个原因,按照相关顺序如下:

  1. 移除命名空间需要迭代并修改文件的所有节点,而这对于 Scrapy 爬取的所有文档操作需要一定的性能消耗
  2. 会存在这样的情况,确实需要使用命名空间,但有些元素的名字与命名空间冲突。尽管这些情况非常少见。

转载自:http://www.cnblogs.com/sufei-duoduo/p/5868027.html

时间: 2024-08-29 02:41:27

[转]scrapy 选择器官方文档的相关文章

scrapy spider官方文档

Spiders Spider类定义了如何爬取某个(或某些)网站.包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item). 换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方. 对spider来说,爬取的循环类似下文: 以初始的URL初始化Request,并设置回调函数. 当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数. spider中初始的request是通过调用 start_requests

python爬虫----(4. scrapy框架,官方文档以及例子)

官方文档: http://doc.scrapy.org/en/latest/ github例子: https://github.com/search?utf8=%E2%9C%93&q=scrapy 剩下的待会再整理...... 买饭去......       --2014年08月20日19:29:20 python爬虫----(4. scrapy框架,官方文档以及例子)

Android Studio官方文档之构建和运行你的APP

Android Studio官方文档之构建和运行你的APP 本文由MTJH翻译,jkYishon审校. 前言 默认情况下,Android Studio设置新的项目并且部署到模拟器或者真机设备上,只需要点击几下.使用即时运行,你并不需要构建一个新的APK即可将改变后的方法和现有的应用资源应用到一个正在运行的应用程序中,所以代码的改变是即时可见的. 点击Run来构建并运行你的APP.Android Studio通过Gradle构建你的App,选择一个部署的设备(模拟器或连接的设备),然后把你的APP

Spring Cloud官方文档中文版-声明式Rest客户端:Feign

官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#spring-cloud-feign 文中例子我做了一些测试在:http://git.oschina.net/dreamingodd/spring-cloud-preparation Declarative REST Client: Feign 声明式Rest客户端:Feign Feign is a declarative web service client. It

【苦读官方文档】2.Android应用程序基本原理概述

官方文档原文地址 应用程序原理 Android应用程序是通过Java编程语言来写.Android软件开发工具把你的代码和其它数据.资源文件一起编译.打包成一个APK文件,这个文档以.apk为后缀,保存了一个Android应用程序全部的内容.Android设备通过它来安装相应的应用. 一旦安装到设备上.每一个Android应用程序就执行在各自独立的安全沙盒中: Android系统是一个多用户的Linux系统.每一个应用都是一个用户. Android系统默认会给每一个应用分配一个唯一的用户ID(这个

Spring Boot 官方文档入门及使用

个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问题. 其他说明:如果对Spring Boot没有概念,请先移步上一篇文章 Spring Boot 学习.本篇原本是为了深入了解下Spring Boot而出现的. 另外,Spring Boot 仍然是基于Spring的,建议在赶完工之后深入学习下Spring,有兴趣可以看看我的 Spring 4 官方文档学习(十一)Web MVC 框架 .欢迎探讨,笑~

【cocos2d-js官方文档】十九、Cocos2d-JS单文件引擎使用指引

这篇指引主要介绍如何使用从在线下载工具下载下来的Cocos2d-JS的单文件引擎. 你有可能下载了下面三个版本中的一个: Cocos2d-JS Full Version: 完整版引擎包含Cocos2d-JS引擎的所有功能特性以及所有扩展,使用这个版本可以帮助你发掘Cocos2d-JS令人惊艳的创造力和可能性.你可以从官方文档首页中查看Cocos2d-JS所支持的特性列表. Cocos2d-JS Lite Version: 精简版本只包含Cocos2d-JS的核心特性,它的优势是稳定,轻量,简单易

使用oracle官方文档(11G)简单举例

使用oracle官方文档(11G)举例 以下正是oracle官方文档界面,想要学好oracle,读官方文档是必经之路,此文为给初学者大致了解官方文档的使用,对官方文档有一个更直观的认识.文档可通过文章关联的链接查看到,或登录到oracle官网查看(内容更加丰富). <官方文档>阅读来源 官网链接:Oracle11G官方文档      下载地址:Oracle11G官方文档下载 以下,简单几个例子,帮助读者对于文档的使用有进一步的理解: [举例1]:在Windows下远程连接数据库使用的指令是什么

Hive官方文档

Hive官方文档 内容列表 Cloudera制作的Hive介绍视频 安装与配置 系统需求 安装Hive发行版 从Hive源码编译 运行Hive 配置管理概览 运行时配置 Hive, Map-Reduce 与本地模式 错误日志 DDL 操作 元数据存储 DML 操作 SQL 操作 查询示例 SELECTS 和 FILTERS GROUP BY JOIN MULTITABLE INSERT STREAMING Simple Example Use Cases MovieLens User Ratin