小白学 Python 爬虫(35):爬虫框架 Scrapy 入门基础(三) Selector 选择器

人生苦短,我用 Python

前文传送门:

小白学 Python 爬虫(1):开篇

小白学 Python 爬虫(2):前置准备(一)基本类库的安装

小白学 Python 爬虫(3):前置准备(二)Linux基础入门

小白学 Python 爬虫(4):前置准备(三)Docker基础入门

小白学 Python 爬虫(5):前置准备(四)数据库基础

小白学 Python 爬虫(6):前置准备(五)爬虫框架的安装

小白学 Python 爬虫(7):HTTP 基础

小白学 Python 爬虫(8):网页基础

小白学 Python 爬虫(9):爬虫基础

小白学 Python 爬虫(10):Session 和 Cookies

小白学 Python 爬虫(11):urllib 基础使用(一)

小白学 Python 爬虫(12):urllib 基础使用(二)

小白学 Python 爬虫(13):urllib 基础使用(三)

小白学 Python 爬虫(14):urllib 基础使用(四)

小白学 Python 爬虫(15):urllib 基础使用(五)

小白学 Python 爬虫(16):urllib 实战之爬取妹子图

小白学 Python 爬虫(17):Requests 基础使用

小白学 Python 爬虫(18):Requests 进阶操作

小白学 Python 爬虫(19):Xpath 基操

小白学 Python 爬虫(20):Xpath 进阶

小白学 Python 爬虫(21):解析库 Beautiful Soup(上)

小白学 Python 爬虫(22):解析库 Beautiful Soup(下)

小白学 Python 爬虫(23):解析库 pyquery 入门

小白学 Python 爬虫(24):2019 豆瓣电影排行

小白学 Python 爬虫(25):爬取股票信息

小白学 Python 爬虫(26):为啥买不起上海二手房你都买不起

小白学 Python 爬虫(27):自动化测试框架 Selenium 从入门到放弃(上)

小白学 Python 爬虫(28):自动化测试框架 Selenium 从入门到放弃(下)

小白学 Python 爬虫(29):Selenium 获取某大型电商网站商品信息

小白学 Python 爬虫(30):代理基础

小白学 Python 爬虫(31):自己构建一个简单的代理池

小白学 Python 爬虫(32):异步请求库 AIOHTTP 基础入门

小白学 Python 爬虫(33):爬虫框架 Scrapy 入门基础(一)

小白学 Python 爬虫(34):爬虫框架 Scrapy 入门基础(二)

引言

我们之前有介绍过通过 pyquery 、 Beautiful Soup 、 lxml 来提取网页数据。

但是在 Scrapy 中,同样也提供了自己独有的数据提取方式,即 Selector(选择器)。Selector 是基于 lxml 来构建的,支持 XPath 选择器、CSS 选择器以及正则表达式,功能全面,解析速度和准确度非常高。

独立使用

Scrapy Selectors 是 Parsel 库的包装。包装的目的是提供与 Scrapy Response 对象的更好的集成。

Parsel 是一个独立的 Web 抓取库,无需 Scrapy 即可使用。它在后台使用 lxml 库,并在 lxml API 之上实现了一个简单的 API 。这意味着 Scrapy 选择器的速度和解析精度与 lxml 非常相似。

我们可以写一个简单的示例代码来测试一下 Selectors 的单独使用。

from scrapy import Selector

body = '<html><head><title>Hello Python</title></head></html>'
selector = Selector(text=body)
title = selector.xpath('//title/text()').extract_first()
print(title)

执行结果如下:

Hello Python

这个简单的示例我们并没有在 Scrapy 框架中执行,而是把 Scrapy 中的 Selector 单独拿出来使用了。

Selector 的使用同其他解析库类似,如果方便的话,我们也可以在其他项目中直接使用 Selector 来提取数据。

Scrapy Shell

由于 Selector 主要是与 Scrapy 结合使用,如 Scrapy 的回调函数中的参数 response 直接调用 xpath() 或者 css() 方法来提取数据,所以在这里我们借助 Scrapy shell 来模拟 Scrapy 请求的过程,来讲解相关的提取方法。

这里我们借助官方文档的示例进行演示。

https://docs.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>

首先,让我们开启 Scrapy shell,在命令行输入如下命令:

scrapy shell https://docs.scrapy.org/en/latest/_static/selectors-sample1.html

这时,我们进入了 Scrapy Shell 模式,其实就是 Scrapy 发起了一次请求,然后把一些可操作的变量传递给我们:

Xpath 选择器

目前我们在 Scrapy shell 之中,这里我们主要操作的对象是 response 。

response 有一个属性是 selector ,我们可以通过调用 response.selector.xpath 对数据进行获取,同时, Scrapy 为我们提供了两个更加简洁的方法, response.xpath() 和 response.css() ,这两个方法完全等同于 response.selector.xpath() 和 response.selector.css() 。

出于写法上的简便考虑,小编后续的代码将全部使用 response.xpath() 和 response.css() 。

首先,我们简单的获取一下 a 标签:

>>> result = response.xpath('//a')
>>> result
[<Selector xpath='//a' data='<a href="image1.html">Name: My image ...'>, 
<Selector xpath='//a' data='<a href="image2.html">Name: My image ...'>, 
<Selector xpath='//a' data='<a href="image3.html">Name: My image ...'>, 
<Selector xpath='//a' data='<a href="image4.html">Name: My image ...'>, 
<Selector xpath='//a' data='<a href="image5.html">Name: My image ...'>]

>>> type(result)
<class 'scrapy.selector.unified.SelectorList'>

这里我们获取到的结果是由 Selector 组成的列表: SelectorList 。

它的类型是 scrapy.selector.unified.SelectorList

SelectorList 和 Selector 都可以继续调用 xpath() 和 css() 等方法来进一步提取数据。

接着上面的例子,我们继续尝试获取 a 标签中的 img 标签:

>>> result.xpath('./img')
[<Selector xpath='./img' data='<img src="image1_thumb.jpg">'>, 
<Selector xpath='./img' data='<img src="image2_thumb.jpg">'>, 
<Selector xpath='./img' data='<img src="image3_thumb.jpg">'>, 
<Selector xpath='./img' data='<img src="image4_thumb.jpg">'>, 
<Selector xpath='./img' data='<img src="image5_thumb.jpg">'>]

这里我们获取到了所有的 a 标签中的 img 标签。

注意: 选择器的最前方加 .,这代表提取元素内部的数据,如果没有加点,则代表从根节点开始提取。

此处我们用了./img 的提取方式,则代表从 a 节点里进行提取。如果此处我们用 //img ,则还是从 html 节点里进行提取。

现在我们已经获得了 Selector 类型的节点 a ,如果我们想要将 a 节点元素提取出来,可以使用 extract() 方法,如下:

>>> result.extract()
['<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>']

这里我们如果想要获得内容的文本内容,可以使用 /text() ,如果想要获取 href 属性的内容可以使用 /@href

我们来看一个完整的示例:

>>> response.xpath('//a[@href="image1.html"]/text()').extract()
['Name: My image 1 ']

这里我们限制的结果,只查到的一条数据,很多情况下我们都会获得多条数据,这时如果想获取第一个元素的内容,可以使用索引的方式,如下:

>>> response.xpath('//a/text()').extract()[0]
'Name: My image 1 '

这样其实有一点点的小问题,如果当前我们需要的列表为空,这里直接会产生数组越界的异常。

Scrapy 为我们提供了另一个方法 extract_first() ,专门用来解决这个问题,上面的示例可以改写成下面的样子:

>>> response.xpath('//a/text()').extract_first()
'Name: My image 1 '

同时我们也可以为 extract_first() 方法设置一个默认值参数,这样当 XPath 规则提取不到内容时会直接使用默认值。

>>> response.xpath('//a[@href="image1"]/text()').extract_first('Default')
'Default'

CSS 选择器

我们接着看 CSS 选择器,还是上面的示例,小编这里就不多 BB 了,直接上示例:

>>> response.css('a')
[<Selector xpath='descendant-or-self::a' data='<a href="image1.html">Name: My image ...'>, 
<Selector xpath='descendant-or-self::a' data='<a href="image2.html">Name: My image ...'>, 
<Selector xpath='descendant-or-self::a' data='<a href="image3.html">Name: My image ...'>, 
<Selector xpath='descendant-or-self::a' data='<a href="image4.html">Name: My image ...'>, 
<Selector xpath='descendant-or-self::a' data='<a href="image5.html">Name: My image ...'>]

我们同样可以进行属性选择和嵌套选择:

>>> response.css('a[href="image1.html"]').extract()
['<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>']
>>> response.css('a[href="image1.html"] img').extract()
['<img src="image1_thumb.jpg">']

接下来获取文本值和属性值的方法稍有区别:

>>> response.css('a[href="image1.html"]::text').extract()
['Name: My image 1 ']
>>> response.css('a[href="image1.html"] img::attr(src)').extract()
['image1_thumb.jpg']

获取文本和属性需要用 ::text::attr() 的写法。

当然,我们的 CSS 选择器和 Xpath 选择器一样可以嵌套选择,一个简单的小示例感受下:

>>> response.xpath('//a').css('img').xpath('@src').extract()
['image1_thumb.jpg', 'image2_thumb.jpg', 'image3_thumb.jpg', 'image4_thumb.jpg', 'image5_thumb.jpg']

Selector 选择器就先介绍到这里了,更多的内容和用法可以参考官方文档:https://docs.scrapy.org/en/latest/topics/selectors.html

本文没什么代码,所以示例代码就不放了。

posted @ 2020-01-09 09:00  极客挖掘机  阅读(871)  评论(0编辑  收藏  举报