首先要明确的是,其实所有的FeedExporter都是类,里面封装了一般进行io操作的方法。因此,要怎么输出呢?其实从技术实现来说,在生成item的每一步调用其进行储存都是可以的,只不过为了更加符合scrapy的架构,一般都是在Pipeline中使用FeedExporter的。

每一个Exporter的使用都是类似的:

在settings.py中写入相应的配置,

在pipeline中调用exporter:

  exporter.start_exporter()

  exporter.export_item()

  exporter.finish_exporter()

其它工作都已经由scrapy封装好了,所以就不需要再进行额外设定了。

由于item的输出一般是连续输出的,因此可以将export开始和结束的方法放到spider_opened和spider_closed中启动。

以将item输出到json文件为例,下面是相关的配置和写法:

在settings.py中的配置:

 FEED_FORMAT = 'json' # 输出格式
FEED_EXPORTERS_BASE = {
'json': 'scrapy.exporters.JsonItemExporter',
'jsonlines': 'scrapy.exporters.JsonLinesItemExporter',
}

在pipeline中的设定:

 class MyCustomPipeline(object):
def __init__(self):
self.files = {} @classmethod
def from_crawler(cls, crawler): # 生成pipeline实例的方法
pipeline = cls()
crawler.signals.connect(pipeline.spider_opened, signals.spider_opened) # 将spider_opened连接到信号上,当spider打开时执行spider_opened方法
crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
return pipeline
def spider_opened(self, spider): #
file = open('%s_ip.json' % spider.name, 'w+b') # 生成文件描述符
self.files[spider] = file # 保存描述符的引用
self.exporter = JsonLinesItemExporter(file) # 实例化一个Exporter类
self.exporter.start_exporting() # 开始输出 def spider_closed(self,spider):
self.exporter.finish_exporting() # 结束输出
#print('*'*50)
file = self.files.pop(spider)
#print(file.name)
file.close() def process_item(self, item, spider):
self.exporter.export_item(item) # 正式输出
return item

那么怎样输出到mysql数据库中呢?

  实际上scrapy自带的FeedExporter中并没有输出到关系型数据库的输出器,因此只能在pipelines中自己定义函数进行处理。由于scrapy是基于twisted异步框架开发的,使用传统的MySQLdb等mysql连接库会出现阻塞。为此,twisted提供了异步数据库实现方法,也就是使用连接池的方式进行交互。

from twisted.enterprise import adbapi
self.dbpool = adbapi.ConnectPool(xxxx) # 生成连接池对象
yield self.dbpool.runInteraction(interaction_function, arg) # 返回异步处理数据库交互的方法

具体使用:

假设已经在配置文件settings.py中设定了

 MYSQL_PIPELINE_URI = 'mysql://root:root@localhost/proxyip' #MySQL的uri

pipelines.py文件中的设置:

 class MySQLPipeline(object):

     def __init__(self, mysql_url):
'''创建连接池'''
# 储存以便将来引用
self.mysql_url = mysql_url
# 报告连接错误
self.report_connection_error = True
# 解析mysql的uri,并初始化dbpool
conn_kwargs = MySQLPipeline.parse_mysql_url(mysql_url)
self.dbpool = adbapi.ConnectionPool('MySQLdb',
charset='utf8',
use_unicode=True,
connect_timeout=5,
**conn_kwargs) @classmethod
def from_crawler(cls, crawler):
'''检索crawler,获取settings'''
# Get url from settings
mysql_url = crawler.settings.get('MYSQL_PIPELINE_URI', None)
# 如果没有配置uri,触发错误
if not mysql_url:
raise NotConfigured
# 生成MySQLPipeline实例
return cls(mysql_url) def close_spider(self, spider):
'''spider关闭时关闭连接池'''
self.dbpool.close()
@defer.inlineCallbacks
def process_item(self, item, spider):
'''处理item,将其传入mysql数据库'''
logger = spider.logger
try:
yield self.dbpool.runInteraction(MySQLPipeline._do_replace, item)
except MySQLdb.OperationalError:
if self.report_connection_error:
print('Can not connect to MySQL:%s'%self.mysql_url)
self.report_connection_error = False else:
print(traceback.format_exc())
# 返回item给下一阶段
defer.returnValue(item) @staticmethod
def _do_replace(tx, item):
'''实现具体的替换操作'''
sql = '''INSERT INTO ips(ip, port, protocol, speed, auth_time, is_transparent) VALUES(%s, %s, %s, %s, %s, %s)'''
args = (
item['ip'],
item['port'],
item['protocol'],
item['speed'],
item['auth_time'],
item['is_transparent'],
)
tx.execute(sql, args) @staticmethod
def parse_mysql_url(mysql_url):
'''通过url获取数据库连接的参数,提供给adbapi的连接池''' params = dj_database_url.parse(mysql_url)
conn_kwargs = {}
conn_kwargs['host'] = params['HOST']
conn_kwargs['user'] = params['USER']
conn_kwargs['passwd'] = params['PASSWORD']
conn_kwargs['db'] = params['NAME']
conn_kwargs['port'] = params['PORT']
# 删除空值
conn_kwargs = dict((k,v) for k,v in conn_kwargs.iteritems() if v) return conn_kwargs

Scrapy笔记:持久化,Feed exports的使用的更多相关文章

  1. Scrapy笔记03- Spider详解

    Scrapy笔记03- Spider详解 Spider是爬虫框架的核心,爬取流程如下: 先初始化请求URL列表,并指定下载后处理response的回调函数.初次请求URL通过start_urls指定, ...

  2. Scrapy笔记06- Item Pipeline

    Scrapy笔记06- Item Pipeline 当一个item被蜘蛛爬取到之后会被发送给Item Pipeline,然后多个组件按照顺序处理这个item. 每个Item Pipeline组件其实就 ...

  3. Learning Scrapy笔记(六)- Scrapy处理JSON API和AJAX页面

    摘要:介绍了使用Scrapy处理JSON API和AJAX页面的方法 有时候,你会发现你要爬取的页面并不存在HTML源码,譬如,在浏览器打开http://localhost:9312/static/, ...

  4. Learning Scrapy笔记(零) - 前言

    我已经使用了scrapy有半年之多,但是却一直都感觉没有入门,网上关于scrapy的文章简直少得可怜,而官网上的文档(http://doc.scrapy.org/en/1.0/index.html)对 ...

  5. scrapy的持久化相关

    终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作. 需求是:将糗百首页中段子的内容和标 ...

  6. 11.scrapy框架持久化存储

    今日概要 基于终端指令的持久化存储 基于管道的持久化存储 今日详情 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的 ...

  7. scrapy之持久化存储

    scrapy之持久化存储 scrapy持久化存储一般有三种,分别是基于终端指令保存到磁盘本地,存储到MySQL,以及存储到Redis. 基于终端指令的持久化存储 scrapy crawl xxoo - ...

  8. scrapy框架持久化存储

    基于终端指令的持久化存储 基于管道的持久化存储 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文 ...

  9. 转 Scrapy笔记(5)- Item详解

    Item是保存结构数据的地方,Scrapy可以将解析结果以字典形式返回,但是Python中字典缺少结构,在大型爬虫系统中很不方便. Item提供了类字典的API,并且可以很方便的声明字段,很多Scra ...

  10. 11,scrapy框架持久化存储

    今日总结 基于终端指令的持久化存储 基于管道的持久化存储 今日详情 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的 ...

随机推荐

  1. Codeforces Round #464 (Div. 2) E. Maximize!

    题目链接:http://codeforces.com/contest/939/problem/E E. Maximize! time limit per test3 seconds memory li ...

  2. Harbor HA部署-使用Ceph RADOS后端

    1. 前言 Harbor 1.4.0版本开始提供了HA部署方式,和非HA的主要区别就是把有状态的服务分离出来,使用外部集群,而不是运行在本地的容器上.而无状态的服务则可以部署在多个节点上,通过配置上层 ...

  3. (JAVA指针),对象引用问题

    引出指针 从表面上看JAVA是没有指针的,或者是说,弱化了指针.但是指针在JAVA中还是真真切切存在的.在Java中我们称之为引用. String a;//引用为空 String a  = new S ...

  4. A JavaScript Image Gallery

    childNodes property:  The childNodes property is a way of getting information about the children of ...

  5. 5.2 pandas 常用函数清单

    文件读取 df = pd.read_csv(path='file.csv') 参数:header=None 用默认列名,0,1,2,3... names=['A', 'B', 'C'...] 自定义列 ...

  6. C#串口扫描枪的简单实现

    原文:C#串口扫描枪的简单实现 串口扫描枪的简单实现 基于串口通讯的扫描枪的实现,主要借助SerialPort类,表示串行端口资源.实现很简单: 工具:usb转RS232转接头/个,扫描枪/套, 扫描 ...

  7. SQL调优--记一次表统计信息未及时更新导致查询超级慢

                某日同事丢给我一个看上去复杂的查询(实际就涉及两张表,套来套去)说只是换了日期条件,但一个查询5秒出数据,一个根本查不出来.现在整理下解决过程,及涉及的知识点. 若有不正之处, ...

  8. 设计模式之第16章-代理模式(Java实现)

    设计模式之第16章-代理模式(Java实现) “现在朋友圈真是太让人蛋疼了啊.”“怎么说?”“一堆代理,各种卖东西的,看着好烦人.”“哎,删了呗.”“都是朋友,哪里好意思删啊.”“这倒也是...哎,迫 ...

  9. IOS开发学习笔记006 - 指针

    C语言 指针 简单使用如下: int *p;//定义 int a = 10; p = &a;//赋值 int * b = &a;//定义并赋值 定义格式:类型 *指针变量名: 注意事项 ...

  10. selenium webdriver——元素操作

    #Author:xiaoxiao from selenium import webdriver import time def abcd(): driver = webdriver.Firefox() ...