Python爬虫之Scrapy框架

Scrapy初探

$ pip install scrapy  #安装
>>> import scrapy  #在Python中测试能否导入Scrapy模块
>>> scrapy.version_info  #显示版本号
$ scrapy  #在shell中测试能否执行
$ scrapy startproject [project-name]  #在指定目录执行创建命令

编写Spider

对于用户来说,Spider是最核心的组件。该框架中的数据流如图所示:

对象 描述
REQUEST Scrapy中HTTP请求对象
RESPONSE Scrapy中HTTP响应对象
ITEM 从页面中爬取的一项数据

实现一个Spider需要4个步骤:

  1. 继承scrapy.Spider。
  2. 为Spider取名。
  3. 设定起始爬取点。
  4. 实现页面解析函数。

使用Selector提取数据

在Python中常用以下模块处理HTTP文本解析问题:

  • BeautifulSoup(API简洁易用,解析速度较慢)
  • lxml(API相对复杂,解析速度更快)

Scrapy综合上述两者优点实现了Selector类,是基于lxml库构建的,并简化了API接口。在Scrapy中使用Selector对象提取页面中的数据,使用时先通过XPath或CSS选择器选中页面中要提取的数据,然后进行提取。

  1. XPath

    即XML路径语言(XML Path Language),是一种用来确定xml文档中某部分位置的语言。基本语法如下表:

    <!-- 表达式 描述
    / 选中文档的跟(root)
    . 选中当前节点
    .. 选中当前节点的父节点
    ELEMENT 选中子节点中所有ELEMENT元素节点
    //ELEMENT 选中后代节点中所有ELEMENT元素节点
    * 选中所有元素子节点
    text() 选中所有文本子节点
    @ATTR 选中名为ATTR的属性节点
    @* 选中所有属性节点
    [谓语] 谓语用来查找某个特定的节点或者包含某个特定值的节点

    详细文档

  2. CSS选择器

    是一种用来确定HTML文档中某部分位置的语言。

    <!-- 表达式 描述 例子
    * 选中所有元素 *
    E 选中E元素 p
    E1,E2 选中E1和E2元素 div,pre
    E1 E2 选中E1后代元素中的E2元素 div p
    E1>E2 选中E1子元素中的E2元素 div>p
    E1+E2 选中E1兄弟元素中的E2元素 p+strong
    .CLASS 选中CLASS属性包含CLASS的元素 .info
    #ID 选中id属性为ID的元素 #main
    [ATTR] 选中包含ATTR属性的元素 [href]
    [ATTR=VALUE] 选中包含ATTR属性且值为VALUE的元素 [method=post]
    [ATTR~=VALUE] 选中包含ATTR属性且值包含VALUE的元素 [class~=clearfix]
    E:nth-child(n) 选中E元素,且该元素必须是其父元素的第n个子元素 a:nth-child(1)
    E:nth-last-child(n) 选中E元素,且该元素必须是其父元素的倒数第n个子元素 a:nth-last-child(2)
    E:first-child 选中E元素,且该元素必须是其父元素的第一个子元素 a:first-child
    E:last-child 选中E元素,且该元素必须是其父元素的倒数第一个子元素 a:last-child
    E:empty 选中没有子元素的E元素 div:empty
    E::text 选中E元素的文本节点(Text Node) p::text

    详细文档

使用Item封装数据

Scrapy提供了以下两个类,用户可以使用它们自定义数据类,封装爬取到的数据:

  • Item基类

    自定义数据类的基类。(例如一个商品Item)

  • Field类

    用来描述自定义数据类包含哪些字段。(例如商品的名字和价格)

自定义一个数据类,只需继承Item,并创建一系列Filed对象的类属性即可。

使用Item Pipeline处理数据

在Scrapy中,Item Pipeline是处理数据的组件,一个Item Pipeline就是一个包含特定接口的类,通常只负责一种功能的数据处理,在一个项目中可以同时启用多个Item Pipeline,他们按指定次序级联起来,形成一条数据处理流水线。以下是Item Pipeline的几种典型应用:

  • 清晰数据。
  • 验证数据的有效性。
  • 过滤掉重复的数据。
  • 将数据存入数据库。

在创建一个Scrapy项目时,会自动生成一个pipelines.py文件,它用来放置用户自定义的Item Pipeline。

在Scrapy中,Item Pipeline是可选的组件,想要启用某个(或某些)Item Pipeline,需要配置文件settings.py中进行配置:

ITEM_PIPELINES = {
  'example.pipelines.ExamplePipeline': 300,
}

ITEM_PIPELINES 是一个字典,我们把想要启用的Item Pipeline添加到这个字典中,其中每一项的键是每一个Item Pipeline类的导入路径,值是一个0~1000的数字,同时启用多个Item Pipeline时,Scrapy根据这些数值决定各Item Pipeline处理数据的先后次序,数值小的在前。

使用LinkExtractor提取链接

Scrapy提供了一个专门用于提取链接的类LinkExtracteor,在提取大量链接或提取规则比较复杂时,使用LinkExtractor更加方便。下面依次介绍LinkExtractor构造器的各个参数:

  • allow
    接收一个正则表达式或一个正则表达式列表,提取绝对url与正则表达式匹配的链接,如果该参数为空(默认),就提取全部链接。

  • deny

    与allow相反,排除绝对url与正则表达式的链接。

  • allow_domains

    接收一个域名或一个域名列表,提取到指定域的链接。

  • deny_domains

    与allow_domains相反,排除到指定域的链接。

  • restrict_xpaths

    接受一个XPath表达式或一个XPath表达式列表,提取XPath表达式选中区域下的链接。

  • restrict_css

    接受一个CSS表达式或一个CSS表达式列表,提取CSS表达式选中区域下的链接。

  • process_value

    接收一个形如func(value)的回调函数。如果传递了该参数,LinkExtractor