Scrapy 框架将爬取的数据通过管道进行处理,即 pipelines.py 文件。

管道处理流程

一、定义 item

item 表示的是数据结构,定义了数据包括哪些字段

class TianqiItem(scrapy.Item):
# define the fields for your item here like: city = scrapy.Field() # 城市
date = scrapy.Field() # 日期
hour = scrapy.Field() # 小时
day = scrapy.Field() # 白天

写法比较固定,不可随意更改;注意没有return

二、在爬虫中生成 item

爬虫组件必须将数据按 item 的结构进行组织

item['city'] = response.xpath('//a[@id="lastBread"]//text()').extract_first()[:-4]
item['date'] = '%s-%s-%s'%(year, month, day)
item['hour'] = hour

注意最终必须  return item;

而且可以 返回多个 item,return item, item2,在某管道中,如果用了 item的key,就自动选择有这个key的item,否则,所有item都会经过该处理。

三、在管道中处理

1. 爬虫生成的 item 自动进入管道;

2. 管道会判断 流入的数据 的类型 是否是 item;【即 item.py 中定义的类型】

3. 如果是 item 类型,进行后续处理,否则,忽略;

4. 返回 item,【必须返回,切记】【返回的 item 流入下一个管道,或者告诉引擎,处理完毕,否则引擎会阻塞】

5. 爬取下一个

class TianqiPipeline(object):
def __init__(self):
self.f = open('save.txt', 'ab') def process_item(self, item, spider):
print(item)
self.f.write(str(dict(item)))
return item def close_spider(self, spider):
self.f.close() class RedisPipeline(object):
def open_spider(self, spider):
host = spider.settings.get('REDIS_HOST', 'localhost')
port = spider.settings.get('REDIS_PORT', 6379)
db = spider.settings.get('REDIS_DB_INDEX', 0) self.redis_con = redis.StrictRedis(host=host, port=port, db=db) def process_item(self, item, spider):
self.redis_con.hmset('%s:%s:%s'%(item['city'], item['date'], item['hour']), dict(item))
return item def close_spider(self, spider):
self.redis_con.connection_pool.disconnect()

代码解释

必选方法:process_item,负责处理数据

可选方法:初始化,只在爬虫启动时进行初始化

可选方法:open_spider,在开始爬取数据之前被调用

可选方法:close_spider,爬取完数据后被调用

可选方法:from_crawler,获取配置

mongodb 示例,包含了上述方法

首先执行 from_crawler 获取配置,在 open_spider 中创建数据库连接

四、启动管道

在settings中配置即可

ITEM_PIPELINES = {
'tianqi.pipelines.TianqiPipeline': 300,
'tianqi.pipelines.RedisPipeline': 301,
}

存在问题

上面这种方式 会作用于所有爬虫;

我们可以在 管道中 判断 是哪个爬虫,根据 spider 参数,或者 根据 item 中的 key,但这种方法很冗余;

更好的做法是在 spider类 中配置 custom_settings 对象

# 类属性
custom_settings = {'ITEM_PIPELINES':
{'getProxy.pipelines.GetproxyPipeline': 300, }}

数据库存储

管道可以实现任何形式的存储,包括文件、数据库等;

而且可以存入各种数据库,如 sqlite、mysql、mongoDB、redis;

上面的例子实现了 redis、mongodb 的存储,其他大同小异,以后有机会再更新。

Scrapy 教程(十)-管道与数据库的更多相关文章

  1. CRL快速开发框架系列教程十二(MongoDB支持)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  2. CRL快速开发框架系列教程十(导出对象结构)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  3. 无废话ExtJs 入门教程十二[下拉列表联动:Combobox_Two]

    无废话ExtJs 入门教程十二[下拉列表联动:Combobox_Two] extjs技术交流,欢迎加群(201926085) 不管是几级下拉列表的联动实现本质上都是根据某个下拉列表的变化,去动态加载其 ...

  4. Unity3D脚本中文系列教程(十六)

    Unity3D脚本中文系列教程(十五) ◆ function OnPostprocessAudio (clip:AudioClip):void 描述:◆  function OnPostprocess ...

  5. 黄聪:Microsoft Enterprise Library 5.0 系列教程(十) Configuration Application Block

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(十) Configuration Application Block 到目前为止,我们使用的模块都是在同一个配置 ...

  6. [转]PostgreSQL教程(十六):系统视图详解

    这篇文章主要介绍了PostgreSQL教程(十六):系统视图详解,本文讲解了pg_tables.pg_indexes.pg_views.pg_user.pg_roles.pg_rules.pg_set ...

  7. Python爬虫框架Scrapy教程(1)—入门

    最近实验室的项目中有一个需求是这样的,需要爬取若干个(数目不小)网站发布的文章元数据(标题.时间.正文等).问题是这些网站都很老旧和小众,当然也不可能遵守 Microdata 这类标准.这时候所有网页 ...

  8. Scrapy教程

    Scrapy教程 原文地址https://doc.scrapy.org/en/latest/intro/tutorial.html 此教程我们假设你已经装好了Scrapy,如果没有请查看安装指南.. ...

  9. RabbitMQ入门教程(十四):RabbitMQ单机集群搭建

    原文:RabbitMQ入门教程(十四):RabbitMQ单机集群搭建 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://b ...

随机推荐

  1. 24.二叉树中和为某一值的路径(python)

    题目描述 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.(注意: 在返回值的list中,数组长度大 ...

  2. JS中for循环嵌套

    for 循环 for语句也是一种前测试循环语句,但它具有在 执行循环之前初始化变量 和 定义循环后要执行的代码的能力 for循环中专门提供了位置来放置循环的三个表达式 定义一个循环需要做实现这三步: ...

  3. SQL 使用分区方法

  4. jQery Datatables回调函数中文

    Datatables——回调函数 ------------------------------------------------- fnCookieCallback:还没有使用过 $(documen ...

  5. 随机数:rand()

    首先我们要对rand&srand有个总体的看法:srand初始化随机种子,rand产生随机数,下面将详细说明.   rand(产生随机数)   表头文件: #include<stdlib ...

  6. Spoj4060 game with probability Problem

    题目链接:Click here Solution: 刚开始还以为博弈论加概率,然而并不是... 设两个状态:\(f(i)\)表示当前剩下\(i\)个石头时,先手的获胜概率,\(g(i)\)为后手的获胜 ...

  7. 【转】jqprint打印时自定义页眉页脚

    需求:自定义页眉,实现打印时分页时每页页眉都显示相同的信息 打印所用插件jqprint 解决方法: <div class="divHeader"> <span s ...

  8. Java 简单工厂

    在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的.但是在一些情况下, new操作符直接生成对象会带来一些问题.举例来说, 许多类型对象的创造需要一 ...

  9. 分布式工作流任务调度系统Easy Scheduler正式开源

    分布式工作流任务调度系统Easy Scheduler正式开源 1.背景 在多位技术小伙伴的努力下,经过近2年的研发迭代.内部业务剥离及重构,也经历一批种子用户试用一段时间后,EasyScheduler ...

  10. Python的datetime与Decimal数据进行json序列化的简单说明

    我们在Python的json.JSONEncoder类中可以查看Python数据序列化为JSON格式的数据时数据类型的对应关系: class JSONEncoder(object): "&q ...