Scrapy带有自己的数据提取机制,称为选择器。scrapy有xpath
和css
两种选择器。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方法
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
是一个HtmlResponse
或XmlResponse
对象,将用于选择和提取数据.
text
是设置编码的变量
tpye
定义选择器类型,可以是html
, xml
或None
(默认)
如果type
为None
,则选择器会根据response类型自动选择最佳类型(请参见下文),如果与text一起使用,则默认为”html” .
如果type
为None
且传递了response
,则从响应类型推断出选择器类型,如下所示:
html
返回 HtmlResponse
类型xml
返回 XmlResponse
类型html
代表其他
如果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)
编译为正则表达式的字符串.
默认情况下,字符实体引用由其对应的字符替换( &
和<
除外). 传递replace_entities
为False
关闭这些替换.
re_first(regex, default=None, replace_entities=True)
应用给定的正则表达式并返回匹配的第一个unicode字符串. 如果不匹配,则返回默认值(如果未提供参数,则返回None
).
默认情况下,字符实体引用由其对应的字符替换( &
和<
除外). 传递replace_entities
为False
关闭这些替换.
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
.
query
与Selector.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字符串列表返回.
默认情况下,字符实体引用将替换为其对应的字符( &
和<
除外.如果False
传递replace_entities
关闭这些替换.
re_first(regex, default=None, replace_entities=True)
对该列表中的第一个元素调用.re()
方法,并以Unicode字符串返回结果. 如果列表为空或正则表达式不匹配任何内容,则返回默认值(如果未提供参数,则返回None ).
默认情况下,字符实体引用将替换为其对应的字符(&
和<
除外.如果False
传递replace_entities
关闭这些替换.
attrib
返回第一个元素的属性字典. 如果列表为空,则返回空dict