Scrapy中选择器的用法

本文介绍Scrapy中选择器的用法。
可以通过官方文档获取更为详细的内容。

简介

在抓取网页时,爬虫需要执行的最常见任务是从HTML源提取数据。
有几个库可用于实现此目的:

  • BeautifulSoup是Python程序员中非常流行的Web抓取库,它根据HTML代码的结构构造一个Python对象,并且合理地处理坏标记,但它有一个缺点:它很慢。
  • lxml是一个XML解析库(也可以解析HTML),它使用基于ElementTree的pythonic API。(lxml不是Python标准库的一部分。)

Scrapy带有自己的提取数据机制。它们被称为选择器,因为它们“选择”由XPathCSS表达式指定的HTML文档的某些部分。

XPath是一种用于在XML文档中选择节点的语言,也可以与HTML一起使用。
CSS是一种将样式应用于HTML文档的语言。它定义选择器以将这些样式与特定HTML元素相关联。

Scrapy选择器是在lxml库上构建的,这意味着它们在速度和解析准确性方面非常相似。

选择器测试网址:https://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 /><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 https://doc.scrapy.org/en/latest/_static/selectors-sample1.html

在这里插入图片描述
在控制台中显示了可用的scrapy变量。

使用选择器

接下来查看selector:

 response.selector

在这里插入图片描述
selector是scrapy内置的一个选择器。利用这个类,我们可以进行许多数据的提取。

由于我们正在处理HTML,因此选择器将自动使用HTML解析器。
因此,通过查看该页面的HTML代码,让我们构建一个XPath来选择title标签内的文本:
在这里插入图片描述

response.selector.xpath('//title/text()')

在这里插入图片描述
返回结果是一个list(其中只有一个元素:selector这个对象),内容就是selector。
如果用.extract_first()方法,就可以直接输出里面的data了。
在这里插入图片描述
上面介绍的是使用xpath进行选择,另一种方法是通过CSS

response.selector.css('title::text').extract_first()

在这里插入图片描述
两种方法都是可以的。
注意到,上面每次都要加上“selector”。其实是可以把它省略掉的,因为scrapy中,提供了两个快捷方式response.xpath()和response.css()。也就是说,上面的命令可以这样写,效果是一样的:

response.xpath('//title/text()').extract_first()
response.css('title::text').extract_first()

在这里插入图片描述

获取图片

我们想拿到id=images这个div里面所有的图片信息——
在这里插入图片描述
可以先通过xpath,拿到这个div:

response.xpath('//div[@id="images"]')

在这里插入图片描述

或者可以直接调用CSS,选择里面所有的imgs标签:

response.xpath('//div[@id="images"]').css('img')

在这里插入图片描述
可以看到由selector组成的list,其中每个元素都是一个selector。
接下来如何提取里面的数据呢?

首先通过css中加入::attr(属性名)可以获得属性。(本例中,属性名应该是src)

 response.xpath('//div[@id="images"]').css('img::attr(src)')

在这里插入图片描述
要获取内容,还要再后面加上extract()方法:

 response.xpath('//div[@id="images"]').css('img::attr(src)').extract()

在这里插入图片描述
相当于从selector中拿出src这个属性(返回一个list),然后使用extract()提取出了实际的数据值。
当然,如果src有多个内容,我们可以通过extract_first()获取第一个内容:

 response.xpath('//div[@id="images"]').css('img::attr(src)').extract_first()

在这里插入图片描述

extract()可以提供默认返回值作为参数,以代替None(未查找到的情况):

 response.xpath('//div[@id="not-exists"]/text()').extract_first(default='not-found')

在这里插入图片描述

获取超链接

现在我们来选择一下超链接,从图中可以看到,超链接是在href这个属性里的:
在这里插入图片描述
使用命令:

response.xpath('//a/@href')

在这里插入图片描述
同样用extract提取:
在这里插入图片描述
当然也可以用CSS代替:

 response.css('a::attr(href)')

在这里插入图片描述
在这里插入图片描述
两种方法都差不多,可以自行选择。

获取文本

在这里插入图片描述
两种方法:

response.xpath('//a/text()').extract()
response.css('a::text').extract()

在这里插入图片描述

更高级的选项

如果我们想要查找属性名称包含image的所有的超链接可以使用contains选项,第一个参数是属性名,第二个属性是要查找的值

response.xpath('//a[contains(@href,"image")]/@href').extract()

在这里插入图片描述
CSS的写法:

response.css('a[href*=image]::attr(href)').extract()

在这里插入图片描述

假如我们要选择所有a标签里的img里面的src属性,用上contains:
在这里插入图片描述

response.xpath('//a[contains(@href,"image")]/img/@src').extract()

在这里插入图片描述
CSS:
注意[]之后要有空格

response.css('a[href*=image] img::attr(src)').extract()

在这里插入图片描述

正则表达式

Selector还有一种使用正则表达式提取数据的方法——.re()
假如我们要提取文本中冒号后的内容:
在这里插入图片描述
直接使用text获取的是所有的文本,那么我们可以使用正则表达式:

 response.css('a::text').re('Name\:(.*)')

注意,\用来对:进行转义。
在这里插入图片描述
如图,成功取得了冒号后的内容。
与extract()方法类似,re也提供了取得列表中第一个元素的方法:re_first()

 response.css('a::text').re_first('Name\:(.*)')

在这里插入图片描述
进一步地,可以使用strip()方法,去掉返回结果中前后的空格:

 response.css('a::text').re_first('Name\:(.*)').strip()

在这里插入图片描述

小结

response为我们提供了几个提取方法:

  • xpath
  • CSS
  • re

返回的结果都是Selector类型,可以进行嵌套循环。

(a) 对css来说:

  • 获取a标签中的文本内容:response.css('a::text')
  • 获取a标签中的某个属性:response.css('a::attr(属性)')

(b)对xpath来说:

  • 获取a标签中的文本内容:response.xpath('//a/text()')
  • 获取a标签中的某个属性:response.xpath('//a/@href')

两种选择方法,写法不同,效果类似。

要从selector变为数据,则在后面加上.extract().extract()_first()
如果要提取更具体的信息,可以用正则表达式的方法,在后面加上 .re() 或 .re()_first 进行嵌套选择。

猜你喜欢

转载自blog.csdn.net/z714405489/article/details/84402851