在前面的文章中,我们讲解了 Spider 开发的大体流程,让大家对 Scrapy 爬虫开发有了更加清晰的理解,接下来继续讲解编写爬虫时使用的一些具体技术,从页面中提取数据是 Spider 最重要的工作之一,接下来我们学习相关内容。
Selector 对象
从页面中提取数据的核心技术是 HTTP 文本解析,在 Python 中常用以下模块处理此类问题:
- BeautifulSoup
BeautifulSoup 是非常流行的 HTTP 解析库,API 简洁易用,但解析速度较慢。 - lxml
lxml 是一套由 C 语言编写的 xml 解析库 libxml2 和 libxslt 的绑定,解析速度更快,API相对复杂。
Scrapy 综合上述两者优点实现了 Selector 类,它是基于 lxml 库构建的,并简化了 API 接口。在 Scrapy 中使用 Selector 对象提取页面中的数据,使用时先通过 XPath 或 CSS 选择器选中页面中要提取的数据,然后进行提取。
下面详细介绍 Selector 对象的使用。
01 创建对象
Selector 类的实现位于 scrapy.selector 模块,创建 Selector 对象时,可将页面的 HTML 文档字符串传递给 Selector 构造器方法的 text 参数:
>>> from scrapy.selector import Selector>>> text = '''... ... ...
Hello
...
Hello Scrapy
... ... Python... C++... ... ... ... '''>>> selector = Selector(text=text)'\n\t\n\t\t
Hello
\n\t\t>
也可以使用一个 Response 对象构造 Selector 对象,将其传递给 Selector 构造器方法的 response 参数:
>>> from scrapy.selector import Selector>>> from scrapy.http import HtmlResponse>>> body = '''... ... ...
Hello
...
Hello Scrapy
... ... Python... C++... ... ... ... '''>>> response = HtmlResponse(url='http://www.example.com',body=body,encoding='utf8')>>> selector = Selector(response=response)>>> selector'\n \n
H...'
>
01 选中数据
调用 Selector 对象的 xpath 方法或 css 方法(传入 XPath 或 CSS 选择器表达式),可以选中文档中的某个或某些部分:
>>> selector_list = selector.xpath('//h1')>>> selector_list['//h1' data= '//h1' data=
xpath 和 css 方法返回一个 SelectorList 对象,其中包含每个被选中部分对应的 Selector 对象,SelectorList 支持列表接口,可使用 for 语句迭代访问其中的每一个 Selector 对象:
>>> for sel in selector_list:... print(sel.xpath('./text()'))... [<Selector xpath='./text()' data='Hello'>][<Selector xpath='./text()' data='Hello Scrapy'>]
Selector
List 对象也有 xpath 和 css 方法,调用它们的行为是:以接收到的参数分别调用其中每一个 Selector 对象的 xpath 和 css 方法,并将所有结果收集到一个新的
Selector
List 对象返回给用户。请看下面的示例:
>>> selector_list.xpath('./text()')['./text()' data= './text()' data=
>>> selector.xpath('.//ul').css('li').xpath('./text()')['./text()' data= './text()' data=
02 提取数据
调用 Selector 或 SelectorList 对象的以下方法可将选中的内容提取:
- extract()
- re()
- extract_first() (SelectorList 专有)
- re_first() (SelectorList 专有)
首先来看
extract 方法,调用 Selector 对象的
extract 方法将返回选中内容的Unicode字符串:
>>> sl = selector.xpath('.//li')>>> sl['.//li' data= './/li' data=>>> sl[0].extract()'Python'>>> sl = selector.xpath('.//li/text()')>>> sl['.//li/text()' data= './/li/text()' data= >>> sl[1].extract()'C++'
与 SelectorList 对象的 xpath 和 css 方法类似, SelectorList 对象的 extract 方法内部会调用其中每个 Selector 对象的 extract 方法,并把所有结果收集到一个列表返回给用户:
>>> sl = selector.xpath('.//li/text()')>>> sl['.//li/text()' data= './/li/text()' data=>>> sl.extract()['Python', 'C++']
Selector
List 对象还有一个 extract_first 方法,该方法返回其中第一个 Selector 对象调用 extract 方法的结果。通常,在
Selector
List 对象中只包含一个 Selector 对象时调用该方法,直接提取出 Unicode 字符串而不是列表,如以下代码:
>>> from scrapy.selector import Selector>>> text = '''... ... ... Hello... ... ... '''>>> selector = Selector(text=text)>>> sl = selector.xpath('.//b')>>> sl['.//b' data=>>> sl.extract()['Hello']>>> sl.extract_first()'Hello'
有些时候,我们想使用正则表达式提取选中内容中的某部分,可以使用 re 方法(两个对象都有该方法):
>>> from scrapy.selector import Selector>>> text = '''... ... Python 教程 价格:88元... Java 教程 价格:100元... C++ 教程 价格:68元... ... '''>>> >>> selector = Selector(text=text)>>> selector.xpath('.//li/b/text()')['.//li/b/text()' data= './/li/b/text()' data= './/li/b/text()' data=>>> selector.xpath('.//li/b/text()').extract()['价格:88元', '价格:100元', '价格:68元']
可以使用 re 提取指定部分,比如只提取价格数字:
>>> selector.xpath('.//li/b/text()').re('\d+')['88', '100', '68']
SelectorList 对象的 re_first 方法同样返回其中的第一个 Selector 对象调用 re 方法的结果:
>>> selector.xpath('.//li/b/text()').re_first('\d+')'88'
内容参考:
Scrapy官方文档、《精通Scrapy网络爬虫》、百度。