1写在前面的话
这次接着上一篇文章来讲Scrapy框架,这次讲的是Scrapy框架里面提供的两种数据提取机制Xpath和CSS,其实除了这两种,我们还可以借助第三方库来实现数据的提取,例如:BeautifulSoup(这个在我的爬虫系列文章中有写过)和lxml(Xml解析库),Scrapy选择器是基于lxml库之上的,所以很多地方都是和lxml相似的。
2Selector选择器
我们首先来说说CSS提取,想要学会CSS的解析,前提当然是学会html和css的基本语法,知道它是怎么构成的。
先给大家一串代码:
# -*- coding: utf-8 -*-import scrapy class ToScrapeCSSSpider(scrapy.Spider): name = "toscrape-css" start_urls = [ 'http://quotes.toscrape.com/', ] def parse(self, response): # 提取class为quote的<div>标签 for quote in response.css("div.quote"): yield { # 提取class为text的<span>的标签内的文本内容 'text': quote.css("span.text::text").extract_first(), # 提取class为author的<small>的标签内的文本内容 'author': quote.css("small.author::text").extract_first(), # 提取class为tags的class为tag的<a>的标签内的文本内容 'tags': quote.css("div.tags > a.tag::text").extract() } next_page_url = response.css("li.next > a::attr(href)").extract_first() if next_page_url is not None: yield scrapy.Request(response.urljoin(next_page_url))
代码的解释我已经写在注释里面了,其实非常的简单,只要大家稍微懂得一点html和css
的基础,基本就能够看出是啥意思,我们只要是对网站进行html的爬取都是一层一层地爬进去,并且每一层的标签都会都会有一个特别的标记,例如:class=“xxx”,这样我们可以通过这种特征来找到特定的数据。
xpath代码:
# -*- coding: utf-8 -*-import scrapy class ToScrapeSpiderXPath(scrapy.Spider): name = 'toscrape-xpath' start_urls = [ 'http://quotes.toscrape.com/', ] def parse(self, response): for quote in response.xpath('//div[@class="quote"]'): yield { 'text': quote.xpath('./span[@class="text"]/text()').extract_first(), 'author': quote.xpath('.//small[@class="author"]/text()').extract_first(), 'tags': quote.xpath('.//div[@class="tags"]/a[@class="tag"]/text()').extract() } next_page_url = response.xpath('//li[@class="next"]/a/@href').extract_first() if next_page_url is not None: yield scrapy.Request(response.urljoin(next_page_url))
其实xpath的代码也是类似的,代码的意思都是一样的,讲到这里相信大家对这两种选择器有了初步理解,下面我细细给大家讲讲每个知识!
3详解Selector
- xpath(query):写入xpath的表达式query,返回该表达式所对应的所有的节点的selector list 列表
- css(query):写入css的表达式query,返回该表达式所对应的所有的节点的selector list 列表
- extract():序列化该节为Unicode字符串并返回list列表
-
extract_first():序列化该节为Unicode字符串并返回第一个元素
-
re(regex):写入正则表达式对数据进行提取,正则表达式我前面的文章详细的写过
xpath路径表达式:
表达式 | 描述 |
nodename | 选取此节点的所有子节点。 |
/ | 从根节点选取。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点。 |
.. | 选取当前节点的父节点。 |
@ | 选取属性。 |
实例:
路径表达式 | 结果 |
bookstore | 选取 bookstore 元素的所有子节点。 |
/bookstore |
选取根元素 bookstore。 注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
//@lang | 选取名为 lang 的所有属性。 |
路径表达式 | 结果 |
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang='eng'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |