Scrapy: xpath与css选择器

本文详细介绍了Scrapy中如何使用XPath和CSS选择器进行网页元素选取。讲解了基本语法,包括子元素、后代元素、谓语语法和其他特殊语法。还探讨了Scrapy选择器的实战应用,如在Scrapy shell中使用response.xpath()和response.css()方法,以及如何结合正则表达式提取数据。最后,提到了选择器的嵌套和.re()方法的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CSS 选择器
表达式说明
*所有节点
#ElementIdID为ElementId的节点
.clsNameclass为clsName的节点
li ali元素下所有a元素
ul + pul下第一个P元素
div#eId > ulid为eId的元素下所有ul元素
div.clsNameclsss为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()’:匹配任意类型的元素

例如:

  1. /div/*:属于div元素的所有子节点
  2. //*:所有元素
  3. //div[@*]:所有带属性的div元素
  4. /div/a | //div/p:所有div元素的a和p元素
  5. //span | //ul:所有span和ul元素
  6. 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 />![](image1_thumb.jpg)</a>
   <a href='image2.html'>Name: My image 2 <br />![](image2_thumb.jpg)</a>
   <a href='image3.html'>Name: My image 3 <br />![](image3_thumb.jpg)</a>
   <a href='image4.html'>Name: My image 4 <br />![](image4_thumb.jpg)</a>
   <a href='image5.html'>Name: My image 5 <br />![](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()方法返回一个类 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>![](image1_thumb.jpg)</a>',
 u'<a href="image2.html">Name: My image 2 <br>![](image2_thumb.jpg)</a>',
 u'<a href="image3.html">Name: My image 3 <br>![](image3_thumb.jpg)</a>',
 u'<a href="image4.html">Name: My image 4 <br>![](image4_thumb.jpg)</a>',
 u'<a href="image5.html">Name: My image 5 <br>![](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']

结合正则表达式使用选择器(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'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值