2.4 Selectors (选择器) Scrapy 核心组件详解:Selectors (选择器) 2.4.1 Selectors 的作用和原理 当我们使用 Scrapy 爬取网页时,首先需要下载网页的 HTML 或 XML 内容。接下来,我们需要从这些内容中提取我们感兴趣的数据,例如商品名称、价格、描述等。Selectors 正是为了解决这个问题而设计的。 Selectors 基于 XPath 或 CSS 选择器表达式,将 HTML 或 XML 文档解析成一个可遍历的树形结构。我们可以使用这些表达式来定位文档中的特定元素,然后提取这些元素的文本、属性值或 HTML 内容。 原理图示: 2.4.
2.4.1 Selectors 的作用和原理
当我们使用 Scrapy 爬取网页时,首先需要下载网页的 HTML 或 XML 内容。接下来,我们需要从这些内容中提取我们感兴趣的数据,例如商品名称、价格、描述等。Selectors 正是为了解决这个问题而设计的。
Selectors 基于 XPath 或 CSS 选择器表达式,将 HTML 或 XML 文档解析成一个可遍历的树形结构。我们可以使用这些表达式来定位文档中的特定元素,然后提取这些元素的文本、属性值或 HTML 内容。
原理图示:
2.4.2 Selectors 的创建和使用
在 Scrapy 中,我们可以使用 scrapy.selector.Selector 类来创建 Selector 对象。通常,我们不需要手动创建 Selector 对象,因为 Scrapy 的 Response 对象已经包含了 Selector 对象。
2.4.2.1 从 Response 对象获取 Selector
Scrapy 的 Response 对象(例如 TextResponse 和 HtmlResponse)包含了 selector 属性,该属性是一个已经初始化好的 Selector 对象,可以直接使用。
import scrapy class MySpider(scrapy.Spider): name = "myspider" start_urls = ["http://example.com"] def parse(self, response): # 直接使用 response.selector title = response.selector.xpath('//title/text()').get() print(f"页面标题: {title}")
2.4.2.2 手动创建 Selector 对象
虽然通常不需要手动创建,但在某些特殊情况下,例如需要处理字符串形式的 HTML 内容时,可以手动创建 Selector 对象。
from scrapy.selector import Selector html_content = """ <html> <head> <title>Example Page</title> </head> <body> <h1>Welcome</h1> <p>This is a paragraph.</p> </body> </html> """ selector = Selector(text=html_content) title = selector.xpath('//title/text()').get() print(f"页面标题: {title}")
2.4.3 XPath 选择器
XPath (XML Path Language) 是一种用于在 XML 文档中定位节点的查询语言。由于 HTML 也可以被视为 XML 的一种形式,因此 XPath 也可以用于解析 HTML 文档。
2.4.3.1 XPath 表达式语法
以下是一些常用的 XPath 表达式语法:
/:从根节点开始选择。
//:从文档中的任何位置选择节点。
.:选择当前节点。
..:选择父节点。
@:选择属性。
text():选择文本内容。
2.4.3.2 XPath 示例
from scrapy.selector import Selector html_content = """ <html> <body> <div class="container"> <h1>Product Name</h1> <p class="description">A detailed description of the product.</p> <span class="price">$19.99</span> <a href="/product/123">View Details</a> </div> </body> </html> """ selector = Selector(text=html_content) # 获取标题文本 title = selector.xpath('//h1/text()').get() print(f"标题: {title}") # 获取描述文本 description = selector.xpath('//p[@class="description"]/text()').get() print(f"描述: {description}") # 获取价格文本 price = selector.xpath('//span[@class="price"]/text()').get() print(f"价格: {price}") # 获取链接的 href 属性 link = selector.xpath('//a/@href').get() print(f"链接: {link}")
2.4.3.3 XPath 函数
XPath 提供了许多有用的函数,可以用于更精确地定位和提取数据。
contains(string, substring):检查字符串是否包含指定的子字符串。
starts-with(string, substring):检查字符串是否以指定的子字符串开头。
ends-with(string, substring):检查字符串是否以指定的子字符串结尾。
string-length(string):返回字符串的长度。
示例:
# 获取包含 "description" 的 class 属性的 p 元素的文本 description = selector.xpath('//p[contains(@class, "description")]/text()').get() print(f"描述: {description}")
2.4.4 CSS 选择器
CSS 选择器是一种用于在 HTML 文档中定位元素的模式。Scrapy 的 Selector 也支持 CSS 选择器,这使得我们可以使用熟悉的 CSS 语法来提取数据。
2.4.4.1 CSS 选择器语法
以下是一些常用的 CSS 选择器语法:
.class:选择具有指定 class 属性的元素。
#id:选择具有指定 id 属性的元素。
element:选择指定类型的元素。
element element:选择指定元素的后代元素。
element > element:选择指定元素的子元素。
element + element:选择紧接在指定元素后的元素。
[attribute]:选择具有指定属性的元素。
[attribute=value]:选择具有指定属性和值的元素。
2.4.4.2 CSS 选择器示例
from scrapy.selector import Selector html_content = """ <html> <body> <div class="container"> <h1>Product Name</h1> <p class="description">A detailed description of the product.</p> <span class="price">$19.99</span> <a href="/product/123">View Details</a> </div> </body> </html> """ selector = Selector(text=html_content) # 获取标题文本 title = selector.css('h1::text').get() print(f"标题: {title}") # 获取描述文本 description = selector.css('p.description::text').get() print(f"描述: {description}") # 获取价格文本 price = selector.css('span.price::text').get() print(f"价格: {price}") # 获取链接的 href 属性 link = selector.css('a::attr(href)').get() print(f"链接: {link}")
2.4.4.3 CSS 伪元素
CSS 伪元素允许我们选择元素的特定部分,例如 ::text 用于选择元素的文本内容,::attr(attribute_name) 用于选择元素的属性值。
2.4.5 提取数据的方法
Selector 对象提供了以下方法来提取数据:
get():返回第一个匹配元素的文本内容或属性值。如果没有匹配的元素,则返回 None。
getall():返回所有匹配元素的文本内容或属性值的列表。
extract():返回第一个匹配元素的序列化字符串(HTML 代码)。如果没有匹配的元素,则返回 None。
extract_first():与 extract() 类似,但只返回第一个匹配元素的序列化字符串。
re(regex):使用正则表达式提取匹配的文本。
re_first(regex):与 re(regex) 类似,但只返回第一个匹配的文本。
示例:
from scrapy.selector import Selector html_content = """ <html> <body> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </body> </html> """ selector = Selector(text=html_content) # 获取所有 li 元素的文本内容 items = selector.xpath('//li/text()').getall() print(f"所有项目: {items}") # 使用正则表达式提取数字 numbers = selector.xpath('//li/text()').re(r'\d+') print(f"所有数字: {numbers}")
2.4.6 选择器的嵌套使用
Selectors 可以嵌套使用,这使得我们可以更精确地定位和提取数据。