网页解析神器-Selector选择器全面解析

本文主要参照scrapy最新官方文档编写。
官方文档直达链接:https://docs.scrapy.org/en/latest/topics/selectors.html

大部分人可能喜欢使用以下三个解析器对网页进行解析:

  • BeautifulSoup:使用方便,支css选择器,但它有个不可忽视的缺点:慢。
  • lxml解析库:采用xpath解析,速度快。
  • pyquery:它提供了和jQuery类似的语法来解析HTML文档,支持CSS选择器
  • re:正则表达式是万能通用的,不过使用它的头疼度我就不用过多解释了。。

但对于某些网页结构俩说,单一的解析方法也许并不是那么方便,如果想嵌套xpath与css选择器甚至正则表达式呢?
好的,你需要了解学习一下强大的Selector选择器,它不仅是能在scrapy框架内部使用,也可导入到其他脚本爬虫中。
而且这更适合经常使用scrapy框架的人的解析习惯。

这里着重介绍在外部使用Selector的方法,(scrapy内部使用无需先实例化,其余操作均相同):

1.导入scrapy,实例化对象

  • 首先导入包,传入网页响应实例化Selector的对象,使用xpath或css解析器解析网页:
from scrapy import Selector
body = 'good'
selector = Selector(text=body) 
>>> selector.xpath('//span/text()').get()
'good'
>>>  selector.css('span::text').get()
'good'

2.提取文本数据,

  • 必须调用选择器.get() 或.getall()方法,如下所示:
from scrapy import Selector

body ="""
    
     
      
      Example website
     
     
      
     
    
    """
>>>selector = Selector(text=body)
>>>selector.xpath('//title/text()').getall()
['Example website']
>>>selector.xpath('//title/text()').get()
'Example website'

.get()总是返回一个结果; 如果有多个匹配,则返回第一个匹配的内容; 如果没有匹配项,则返回None。.getall()返回包含所有结果的列表。

请注意,CSS选择器可以使用CSS3伪元素选择文本或属性节点:

>>> selector.css('title::text').get()
'Example website'

3.选择器返回对象格式

  • 正如你所看到的,.xpath().css()方法返回一个 SelectorList实例,这是新的选择列表。此API可用于快速选择嵌套数据:
>>> selector.css('img').xpath('@src').getall()
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']

如果只想提取第一个匹配的元素,可以调用选择器.get()(或.extract_first()这是以前版本的方法):

>>> selector.xpath('//div[@id="images"]/a/text()').get()
'Name: My image 1 '

4.返回None

  • 如果解析式没有找到元素,则返回:None
>>> selector.xpath('//div[@id="not-exists"]/text()').get() is None
True
  • 当你不希望返回的数据是None时,可以提供默认返回值作为参数,以代替None:
>>> selector.xpath('//div[@id="not-exists"]/text()').get(default='not-found')
'not-found'

5.css选择器的.attrib

  • 可以使用css选择器的.attrib而非xpath的@src采取列表推导式来获取网页结构某属性值:
>>> [img.attrib['src'] for img in selector.css('img')]
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']

  • 作为快捷方式,.attrib也可以直接在SelectorList上使用; 它返回第一个匹配元素的属性,当仅预期单个结果时,例如当通过id选择或在网页上选择唯一元素时,这是最有用的::
>>> selector.css('img').attrib['src']
'image1_thumb.jpg'

6.常用链接提取示例

  • 现在我们将获得基本URL和一些图像链接:
>>> selector.xpath('//base/@href').get()
'http://example.com/'

>>> selector.css('base::attr(href)').get()
'http://example.com/'

>>> selector.css('base').attrib['href']
'http://example.com/'

>>> selector.xpath('//a[contains(@href, "image")]/@href').getall()
['image1.html',
 'image2.html',
 'image3.html',
 'image4.html',
 'image5.html']

>>> selector.css('a[href*=image]::attr(href)').getall()
['image1.html',
 'image2.html',
 'image3.html',
 'image4.html',
 'image5.html']

>>>selector.xpath('//a[contains(@href, "image")]/img/@src').getall()
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']

>>>selector.css('a[href*=image] img::attr(src)').getall()
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']

7.CSS选择器的扩展:Selector支持一些w3c标准的拓展

  • 要选择文本节点,请使用 ::text
  • 选择属性值,用::attr(name)那里的名字是你想要的价值属性的名称

8.嵌套选择器

  • 当解析后不调用.get()或.getall()方法时,将会返回一个选择器列表,我们可在后续继续对该对象进行选择器的嵌套调用:
>>> links = selector.xpath('//a[contains(@href, "image")]')
>>> links.getall()
['Name: My image 1 
', 'Name: My image 2
', 'Name: My image 3
', 'Name: My image 4
', 'Name: My image 5
'] >>> for index, link in enumerate(links): ... args = (index, link.xpath('@href').get(), link.xpath('img/@src').get()) ... print('Link number %d points to url %r and image %r' % args) Link number 0 points to url 'image1.html' and image 'image1_thumb.jpg' Link number 1 points to url 'image2.html' and image 'image2_thumb.jpg' Link number 2 points to url 'image3.html' and image 'image3_thumb.jpg' Link number 3 points to url 'image4.html' and image 'image4_thumb.jpg' Link number 4 points to url 'image5.html' and image 'image5_thumb.jpg'

9.使用正则表达式选择器

  • Selector还有一种.re()使用正则表达式提取数据的方法。但是,与使用 .xpath().css()methods 不同,.re()返回unicode字符串列表。所以你不能构造嵌套的.re()调用。

以下是用于从上面的[HTML代码中提取图像名称的示例:

>>> selector.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']
  • 使用.re_first()提取第一个匹配的字符串:
>>> selector.xpath('//a[contains(@href, "image")]/text()').re_first(r'Name:\s*(.*)')
'My image 1'

10.关于extract()和extract_first()的使用

  • Scrapy仍然支持这些方法,没有计划弃用它们。Scrapy使用文档现在使用.get()和 .getall()方法编写,你可以随自己喜好选用,但显然.get()和 .getall()更简洁。

11.本文未详细深入讲解css、xpath选择器本身语法,需要自己再去w3c学习。

完。

你可能感兴趣的:(网页解析神器-Selector选择器全面解析)