CSS 选择器
表达式 | 说明 |
---|---|
* | 所有节点 |
#ElementId | ID为ElementId的节点 |
.clsName | class为clsName的节点 |
li a | li元素下所有a元素 |
ul + p | ul下第一个P元素 |
div#eId > ul | id为eId的元素下所有ul元素 |
div.clsName | clsss为clsName的div元素 |
ul ~ p | 与ul相邻的所有p元素 |
a[title] | 所有有tittle属性的a元素 |
a[href=“http://www.baidu.com”] | 所有href为指定值的a元素 |
a[href*=“job”] | 所有href属性包含指定值的a元素 |
a[href^=“http”] | 所有href属性值以指定值开头的a元素 |
a[href$=".jpg"] | 素有href属性值以指定值结尾的a元素 |
input[type=radio]:checked | 状态为选中的radio元素 |
div:not(#eleId) | 所有id不是指定值的div元素 |
li:nth-child(3) | 第三个li元素 |
tr:nth-child(2n) | 第偶数个 tr 元素 |
xpath 选择器
xpath是使用路径在xml和html中进行导航的。
基本语法:
- 子元素: 仅指节点下面的第一层元素
- 后代元素:指节点下任意层级的元素
- 父元素、祖先元素同理
表达式 | 说明 |
---|---|
div | 选取所有div元素的所有子元素 |
/div | 选取根元素div |
div/a | 素有属于div的子元素的a元素 |
//div | 所有div元素 |
div//span | 所有属于div元素的后代span元素,无论在那个层级 |
//@class | 选取所有名为class的属性 |
谓语语法
谓语用来查找某个特定的节点或者包含某个指定的值的节点,谓语百放在方括号中。
表达式 | 说明 |
---|---|
/div/p[1] | 属于div子元素的第一个p元素 |
/div/p[last()] | 属于div子元素的最后一个p元素 |
/div/p[last()-1] | 属于div子元素的倒数第二个p元素 |
/div[@lang] | 所有有lang属性的div元素 |
//div[@lang=‘eng’] | 所有lang属性为eng的div元素 |
.//header//span[contains(@class,‘main-title-rating’)]/@title | .符号表示当前路径,一般在循环中使用;contains中表示class中包含指定值元素,@title是取元素的title属性 |
其他语法
- ‘*’ :匹配任意元素
- ‘@*’:匹配任意属性元素
- ‘node()’:匹配任意类型的元素
例如:
- /div/*:属于div元素的所有子节点
- //*:所有元素
- //div[@*]:所有带属性的div元素
- /div/a | //div/p:所有div元素的a和p元素
- //span | //ul:所有span和ul元素
- article/div/p //span:所有属于article元素的div元素的p元素以及所有span元素
scrapy选择器实战
Scrapy选择器构建于 lxml 库之上,这意味着它们在速度和解析准确性上非常相似。
我们将使用 Scrapy shell
(提供交互测试)和位于Scrapy文档服务器的一个样例页面,来解释如何使用选择器:
http://doc.scrapy.org/en/latest/_static/selectors-sample1.html
这里是它的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 /></a>
<a href='image2.html'>Name: My image 2 <br /></a>
<a href='image3.html'>Name: My image 3 <br /></a>
<a href='image4.html'>Name: My image 4 <br /></a>
<a href='image5.html'>Name: My image 5 <br /></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()方法返回一个类 SelectorList 的实例, 它是一个新选择器的列表。这个API可以用来快速的提取嵌套数据。
为了提取真实的原文数据,你需要调用 .extract()方法如下:
>>> response.xpath('//title/text()').extract()
[u'Example website']
如果想要提取到第一个匹配到的元素, 必须调用 .extract_first() selector:
>>> response.xpath('//div[@id="images"]/a/text()').extract_first()
u'Name: My image 1 '
现在我们将得到根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></a>',
u'<a href="image2.html">Name: My image 2 <br></a>',
u'<a href="image3.html">Name: My image 3 <br></a>',
u'<a href="image4.html">Name: My image 4 <br></a>',
u'<a href="image5.html">Name: My image 5 <br></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']
结合正则表达式使用选择器(selectors)
Selector 也有一个 .re()方法,用来通过正则表达式来提取数据。然而,不同于使用 .xpath() 或者 .css() 方法, .re() 方法返回unicode字符串的列表。所以你无法构造嵌套式的 .re() 调用。
下面是一个例子,从上面的 HTML code 中提取图像名字:
>>> 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']
另外还有一个糅合了 .extract_first() 与 .re() 的函数 .re_first() . 使用该函数可以提取第一个匹配到的字符串:
>>> response.xpath('//a[contains(@href, "image")]/text()').re_first(r'Name:\s*(.*)')
u'My image 1'