主页 > 编程资料 > Python >
发布时间:2018-09-27 作者:apizl 阅读:762次

继续入门示例Demo项目:

Scrapy 爬虫入门 Items 与 Item Pipeline

项目默认已经创建好了items和 pipelines


Items

爬取的主要目标就是从非结构性的数据源提取结构性数据,例如网页。 Scrapy spider可以以python的dict来返回提取的数据.虽然dict很方便,并且用起来也熟悉,但是其缺少结构性,容易打错字段的名字或者返回不一致的数据,尤其在具有多个spider的大项目中。。


为了定义常用的输出数据,Scrapy提供了 Item 类。 Item 对象是种简单的容器,保存了爬取到得数据。 其提供了 类似于词典(dictionary-like) 的API以及用于声明可用字段的简单语法。


许多Scrapy组件使用了Item提供的额外信息: exporter根据Item声明的字段来导出数据、 序列化可以通过Item字段的元数据(metadata)来定义、 trackref 追踪Item实例来帮助寻找内存泄露 (see 使用 trackref 调试内存泄露) 等等。



Item Pipeline

当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。


每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。


以下是item pipeline的一些典型应用:


清理HTML数据

验证爬取的数据(检查item包含某些字段)

查重(并丢弃)

将爬取结果保存到数据库中


items.py默认代码:

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class DemoItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass

pipelines.py默认代码:

class DemoPipeline(object):
    def process_item(self, item, spider):
        return item


自定义items:

import scrapy


class DemoItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()  # 存储标题
    url = scrapy.Field()  # 存储地址


在pipelines中对数据就行清洗:

class DemoPipeline(object):
    def process_item(self, item, spider):
            
        title = item["title"]
        url = item["url"]
        """这里插入数据操作代码 比如写入数据库之类的操作"""
        
        return item


回到spiders (dev456.py)文件中, 使用刚刚定义的item:

# -*- coding: utf-8 -*-
import scrapy
from demo.items import DemoItem


class Dev456Spider(scrapy.Spider):
   name = 'dev456'
   allowed_domains = ['456dev.com']
   start_urls = ['http://www.456dev.com/list-1.html']

   def parse(self, response):
      titles = response.xpath("//li/a[contains(@class, 'title')]/text()").extract()
      urls = response.xpath("//li/a[contains(@class, 'title')]/@href").extract()

      for title, url in zip(titles, urls):
         item = DemoItem()
         item["title"] = title
         item["url"] = response.urljoin(url)
         yield item

最后在settings.py中启用pipelines, 取消注释启用默认item pipeline:

Scrapy 爬虫入门 Items 与 Item Pipeline


执行结果:


Scrapy 爬虫入门 Items 与 Item Pipeline

一下子跑完了,因为这只是一页的数据,如何抓取整个栏目的数据呢:

Scrapy 爬虫入门 Items 与 Item Pipeline


通过分析,我们可以知道只要让spider继续请求分页地址解析数据就行了:

# -*- coding: utf-8 -*-
import scrapy
from demo.items import DemoItem


class Dev456Spider(scrapy.Spider):
   name = 'dev456'
   allowed_domains = ['456dev.com']
   start_urls = ['http://www.456dev.com/list-1.html']

   def parse(self, response):
      titles = response.xpath("//li/a[contains(@class, 'title')]/text()").extract()
      urls = response.xpath("//li/a[contains(@class, 'title')]/@href").extract()

      for title, url in zip(titles, urls):
         item = DemoItem()
         item["title"] = title
         item["url"] = response.urljoin(url)
         yield item

      # 下一页数据
      next_url_list = response.xpath("//li[contains(@class, 'next')]/a/@href").extract()
      if next_url_list:
         #  新请求
         yield scrapy.Request(response.urljoin(next_url_list[0]))

新请求默认继续调用parse方法解析数据,循环下去,直到没有下页数据时停止.


附上完整的项目代码:


    Scrapy入门示例 456dev爬虫完整源码 下载

关键字词: