Scrapy带有自己的数据提取机制,称为选择器。scrapy有xpathcss两种选择器。XPath 是一种在XML文档中选择节点的语言,也可以与HTML一起使用。 CSS 是用于将样式应用于HTML文档的语言。它定义选择器,将这些样式与特定的HTML元素相关联。

1.构造选择器

响应对象(response)公开 Selector 实例对 .selector 属性

在response中还包含两个方法: response.xpath()response.css()

使用Selector构造直接从文本构造

>>> from scrapy.selector import Selector
>>> body = '<html><body><span>good</span></body></html>'
>>> Selector(text=body).xpath('//span/text()').get()
'good'

2.使用选择器

为了解释如何使用选择器,我们使用 Scrapy shell 来测试

为了完整起见,下面是完整的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>  

打开虚拟环境,执行

scrapy shell https://docs.scrapy.org/en/latest/_static/selectors-sample1.html

3.提取文本数据

方法描述
.get()始终返回单个结果;如果有多个匹配项,则返回第一个匹配项的内容;如果没有匹配项,则不返回任何匹配项
.getall()返回包含所有结果的列表

如果您是Scrapy的长期用户,则可能熟悉.extract().extract_first()选择器方法. 许多博客文章和教程也正在使用它们. Scrapy仍支持这些方法, 没有计划弃用它们.

但是,现在使用.get().getall()方法编写Scrapy用法文档. 我们认为这些新方法可以使代码更简洁易读.

以下示例显示了这些方法如何相互映射:

1.SelectorList.get()SelectorList.extract_first()相同:

>>> response.css('a::attr(href)').get()
'image1.html'
>>> response.css('a::attr(href)').extract_first()
'image1.html'

2.SelectorList.getall()SelectorList.extract()相同:

>>> response.css('a::attr(href)').getall()
['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html']
>>> response.css('a::attr(href)').extract()
['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html']

3.Selector.get()Selector.extract()相同

>>> response.css('a::attr(href)')[0].get()
'image1.html'
>>> response.css('a::attr(href)')[0].extract()
'image1.html'

4.为了保持一致性,还有Selector.getall() ,它返回一个列表:

>>> response.css('a::attr(href)')[0].getall()
['image1.html']

4.css选择器

css选择器描述
css(‘title::text’).get()提取标签的文本节点
css(‘*::text’).getall()选择当前选择器上下文的所有子代文本节点
css(‘foo::text’).get()获取标签的文本节点
css(‘foo::text’).get(default=’’)获取标签的文本节点,如果没有返回 ''
css(‘a::attr(href)’).getall()获取全部标签的href属性
>>> response.css('title::text').get()
'Example website'

>>> response.css('#images *::text').getall()
['\n   ',
 'Name: My image 1 ',
 '\n   ',
 'Name: My image 2 ',
 '\n   ',
 'Name: My image 3 ',
 '\n   ',
 'Name: My image 4 ',
 '\n   ',
 'Name: My image 5 ',
 '\n  ']

>>> [img.attrib['src'] for img in response.css('img')]
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']
 
 
# 嵌套使用
>>> response.css('img').xpath('@src').getall()
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']

#.attrib 也可以直接在selectorlist上使用;它返回第一个匹配元素的属性:
>>> response.css('img').attrib['src']
'image1_thumb.jpg'

5.xpath选择器

xpath 使用路径表达式在xml和html中进行导航

选取节点

表达式描述
nodename选取此节点的所有子节点
/从根节点选取
//选取匹配所有的元素,而不考虑它们的位置
.选取当前节点
..选取当前节点的父节点
@选取属性

谓语

谓语用来查找某个特定的节点或者包含某个指定的值的节点。谓语被嵌在方括号中[]

表达式描述
//body/div[1]选取body元素下的第一个div元素
//body/div[last()]选取body元素的最后一个div元素
//body/div[last() - 1]选取body元素的倒数第二个元素
//body/div[position() < 3]选取body元素下 前两个div元素
//title[@lang]选取所有拥有名为lang的属性的title元素
//title[@lang=’eng’]选取所有拥有名为lang的属性的title元素
//body/div[price>35.00]选取所有body元素下的div元素,并且price元素的值大于 35.00
//body/div[contains(@class, ‘bbbb’)]匹配body下 div中class属性包含’bbbb’

通配符

通配符描述
*匹配任何元素
@*匹配任何属性的元素
node()匹配任何类型的元素

运算符

运算符描述
|

xpath方法

方法描述
text()提取元素文本节点

6.xpath表达式中的变量

xpath允许您引用xpath表达式中的变量,使用 $somevariable 语法。

下面是一个根据元素的“id”属性值匹配元素的示例,不需要对其进行硬编码(前面已显示)

>>> # `$val` used in the expression, a `val` argument needs to be passed
>>> response.xpath('//div[@id=$val]/a/text()', val='images').get()
'Name: My image 1 '

下面是另一个示例,用于查找 <div> 包含五个的标签 孩子们(在这里我们传递价值 5 作为整数)

>>> response.xpath('//div[count(a)=$cnt]/@id', cnt=5).get()
'images'

7.选择器与正则一起使用

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

8.Selector Objects

classscrapy.selector.Selector(response=None, text=None, type=None, root=None, **kwargs)

Selector实例是对选择其内容某些部分的响应的包装.

response是一个HtmlResponseXmlResponse对象,将用于选择和提取数据.

text是设置编码的变量

tpye定义选择器类型,可以是htmlxmlNone (默认)

如果typeNone ,则选择器会根据response类型自动选择最佳类型(请参见下文),如果与text一起使用,则默认为”html” .

如果typeNone且传递了response ,则从响应类型推断出选择器类型,如下所示:

如果type被设置,则选择类型将被迫并且不会发生检测

xpath(query, namespaces=None, **kwargs)

为了方便起见,此方法可以称为response.xpath()

查找与xpath query匹配的节点,并以所有元素展平的SelectorList实例的形式返回结果. 列表元素也实现Selector接口.

query是一个包含要应用的XPATH查询的字符串.

namespaces是一个可选的prefix: namespace-uri映射(dict),用于向那些在register_namespace(prefix, uri)提供附加前缀. 与register_namespace()相反,这些前缀不会保存供以后调用.

selector.xpath('//a[href=$url]', url="http://www.example.com")

css(query)

为了方便起见,此方法可以称为response.css()

应用给定的CSS选择器并返回SelectorList实例.

query是一个包含要应用的CSS选择器的字符串.

get()

序列化并以单个unicode字符串返回匹配的节点. 编码内容的百分比未引用.

attrib

返回基础元素的属性字典.

re(regex, replace_entities=True)

应用给定的正则表达式,并返回具有匹配项的unicode字符串列表.

regex可以是已编译的正regex也可以是将使用re.compile(regex)编译为正则表达式的字符串.

默认情况下,字符实体引用由其对应的字符替换( &amp;&lt;除外). 传递replace_entitiesFalse关闭这些替换.

re_first(regex, default=None, replace_entities=True)

应用给定的正则表达式并返回匹配的第一个unicode字符串. 如果不匹配,则返回默认值(如果未提供参数,则返回None ).

默认情况下,字符实体引用由其对应的字符替换( &amp;&lt;除外). 传递replace_entitiesFalse关闭这些替换.

register_namespace(prefix, uri)

注册要在此Selector使用的给定名称空间. 如果不注册名称空间,则无法从非标准名称空间选择或提取数据

remove_namespaces()

删除所有名称空间,允许使用无名称空间的xpath遍历文档

bool()

如果选择了任何实际内容,则返回True否则返回False . 换句话说, Selector的布尔值由其选择的内容给出.

getall()

序列化并以1元素的unicode字符串列表返回匹配的节点

9.SelectorList objects

classscrapy.selector.SelectorList

SelectorList类是内置list类的子类,它提供了一些其他方法.

xpath(xpath, namespaces=None, **kwargs)

对该列表中的每个元素调用.xpath()方法,并将其结果展平为另一个SelectorList .

querySelector.xpath()参数相同

namespaces是一个可选的prefix: namespace-uri映射(dict),用于向那些在register_namespace(prefix, uri)提供附加前缀. 与register_namespace()相反,这些前缀不会保存供以后调用.

任何其他命名参数都可以用于在XPath表达式中传递XPath变量的值,例如:

selector.xpath('//a[href=$url]', url="http://www.example.com")

css(query)

对该列表中的每个元素调用.css()方法,并将其结果展平为另一个SelectorList .

getall()

调用此列表的每个元素的.get()方法,并将其结果展平,作为Unicode字符串列表返回

get(default=None)

返回此列表中第一个元素的.get()结果. 如果列表为空,则返回默认值

re(regex, replace_entities=True)

对该列表中的每个元素调用.re()方法,并将其结果展平,作为Unicode字符串列表返回.

默认情况下,字符实体引用将替换为其对应的字符( &amp;&lt;除外.如果False传递replace_entities关闭这些替换.

re_first(regex, default=None, replace_entities=True)

对该列表中的第一个元素调用.re()方法,并以Unicode字符串返回结果. 如果列表为空或正则表达式不匹配任何内容,则返回默认值(如果未提供参数,则返回None ).

默认情况下,字符实体引用将替换为其对应的字符(&amp;&lt;除外.如果False传递replace_entities关闭这些替换.

attrib

返回第一个元素的属性字典. 如果列表为空,则返回空dict

Scrapy 1.7

Scrapy 安装并创建运行爬虫项目(1) Scrapy 命令行工具(2) Scrapy 选择器(3) Scrapy Item(4) Scrapy Item Loaders(5) Scrapy Item Pipeline(6) Scrapy Feed exports(7) Scrapy 架构概览(8) Scrapy 手写一个爬虫(9) Scrapy 知乎模拟登陆 (10) Scrapy源码分析 架构概览(1) Scrapy源码分析 运行入口(2) Scrapy源码分析 核心组件初始化(3) Scrapy源码分析 核心抓取流程(4)