python异步存储数据详解


Posted in Python onMarch 19, 2019

在Python中,数据存储方式分为同步存储和异步存储。同步写入速度比较慢,而爬虫速度比较快,有可能导致数据保存不完整,一部分数据没有入库。而异步可以将爬虫和写入数据库操作分开执行,互不影响,所以写入速度比较快,能够保证数据的完整性。

异步存储数据库大致看分为以下步骤:

1. 在settings中配置Mysql链接需要的参数(主机地址、用户账号、密码、需要操作的表名、编码格式等)
2. 自定义Pipeline,实现from_settings函数
3. from twisted.enterprise import adbapi 引入连接池模块
4. from pymysql import cursors 引入游标模块
5. 在from_settings中,准备链接数据库参数,创建db_pool连接池,创建返回当前类的对象,传入db_pool
6. 实现初始化函数,在初始化函数中,将db_pool赋值self的属性
7. 实现process_item函数
    7.1  query = self.db_pool.runInteraction(执行插入数据操作的函数对象,函数需要参数),并接受执行返回结果
    7.2  query.addErrback(错误回调函数,函数需要参数),添加执行sql失败回调的函数,在回调函数中对错误数据进一步处理
8. 实现插入数据操作的函数,准备sql,执行sql
9. 实现错误回调函数,在回调函数中对错误数据进一步处理 

下面,我们以天堂图片网为例,大致熟悉一下异步存储:

1. 在存储之前,可以选择手动创建数据库(表名、字段名、字段类型等自己定义),也可以选择代码创建。

2. 存储数据之前还得先拿到数据

import scrapy
from ..items import ImgItem
class IvskySpider(scrapy.Spider):
  name = 'ivsky'
  allowed_domains = ['ivsky.com']
  start_urls = ['http://www.ivsky.com/tupian/ziranfengguang/']
  def parse(self, response):
    imgs = response.xpath('//div[@class="il_img"]/a/img')
    for img in imgs:
      alt = img.xpath('@alt').extract_first('')
      src = img.xpath('@src').extract_first('')
      item = ImgItem()
      item['alt'] = alt
      item['src'] = src
 
      yield item

3. 自定义item,并把数据传进去

import scrapy
 
class IvskySpiderItem(scrapy.Item):
  # define the fields for your item here like:
  # name = scrapy.Field()
  pass
 
class ImgItem(scrapy.Item):
 
  alt = scrapy.Field()
  src = scrapy.Field()

4. 接下来就是settings中的配置,代码如下(robots协议记得改为False):

MYSQL_HOST = '127.0.0.1'
MYSQL_USER = 'root'
MYSQL_PW = '123456'
MYSQL_DB = 'ivskydb'
MYSQL_CHARSET = 'utf8'

5. 再然后自定义pipeline,并把该pipeline在settings中配置(设置优先级):

from twisted.enterprise import adbapi
from pymysql import cursors
 
class TwistedMysqlPipeline(object):
 
  # 在调用TwistedMysqlPipeline时,第一个调用该函数
  @classmethod
  def from_settings(cls, settings):
 
    #准备需要用到的链接mysql的参数
    db_prams = dict(
      host=settings['MYSQL_HOST'],
      user=settings['MYSQL_USER'],
      password=settings['MYSQL_PW'],
      db=settings['MYSQL_DB'],
      port=3306,
      use_unicode=True,
      charset=settings['MYSQL_CHARSET'],
      # 指定使用的游标类型
      cursorclass=cursors.DictCursor
    )
    # 创建连接池对象,需要传入两个参数
    # 1.使用操作mysql第三方包名
    # 2.连接数据库需要的参数
    db_pool = adbapi.ConnectionPool('pymysql', **db_prams)
 
    return cls(db_pool)
 
  def __init__(self, db_pool):
    # 将连接池对象赋值self.db_pool属性
    self.db_pool = db_pool
 
  def process_item(self, item, spider):
 
    # 准备sql
    # 执行sql
    # 执行一个将item数据写入数据库的动作
    # 1.执行操作的函数
    # 2.执行函数需要的参数....
    query = self.db_pool.runInteraction(self.insert_item, item)
    # 执行sql出现异常错误时,回调的函数
    query.addErrback(self.handle_error, item, spider)
 
    return item
 
  # 插入数据出现错误时,回调的函数
  def handle_error(self, failure, item, spider):
    print(failure)
    print(item)
 
  # 执行插入数据的函数
  def insert_item(self, cursor, item):
    # 创建sql
    sql = "INSERT INTO ivs(alt,src)VALUES(%s,%s)"
    # 执行sql
    cursor.execute(sql,(item['alt'], item['src']))

6. pipeline在settings中的配置

ITEM_PIPELINES = {
  # 'ivsky_spider.pipelines.MysqlPipeline': 300,
  'ivsky_spider.pipelines.TwistedMysqlPipeline': 300,
}

代码到这里就结束了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
linux系统使用python监控apache服务器进程脚本分享
Jan 15 Python
python的urllib模块显示下载进度示例
Jan 17 Python
Python批量修改文件后缀的方法
Jan 26 Python
Python采用raw_input读取输入值的方法
Aug 18 Python
Python中对列表排序实例
Jan 04 Python
python下MySQLdb用法实例分析
Jun 08 Python
python实现的二叉树定义与遍历算法实例
Jun 30 Python
Python迭代器和生成器定义与用法示例
Feb 10 Python
在Python中实现shuffle给列表洗牌
Nov 08 Python
Python3实现从排序数组中删除重复项算法分析
Apr 03 Python
解决Python paramiko 模块远程执行ssh 命令 nohup 不生效的问题
Jul 14 Python
python多线程爬取西刺代理的示例代码
Jan 30 Python
利用Python半自动化生成Nessus报告的方法
Mar 19 #Python
python实现手机销售管理系统
Mar 19 #Python
Python使用修饰器进行异常日志记录操作示例
Mar 19 #Python
python学生管理系统学习笔记
Mar 19 #Python
Python操作rabbitMQ的示例代码
Mar 19 #Python
Python Matplotlib实现三维数据的散点图绘制
Mar 19 #Python
浅谈python中get pass用法
Mar 19 #Python
You might like
PHP+DBM的同学录程序(4)
2006/10/09 PHP
php学习笔记 面向对象中[接口]与[多态性]的应用
2011/06/16 PHP
怎样给PHP源代码加密?PHP二进制加密与解密的解决办法
2013/04/22 PHP
php常用ODBC函数集(详细)
2013/06/24 PHP
基于PHP给大家讲解防刷票的一些技巧
2015/11/18 PHP
php运行报错Call to undefined function curl_init()的最新解决方法
2016/11/20 PHP
php插件Xajax使用方法详解
2017/08/31 PHP
jquery判断单个复选框是否被选中的代码
2009/09/03 Javascript
JavaScript 垃圾回收机制分析
2013/10/10 Javascript
如何获取select下拉框的值(option没有及有value属性)
2013/11/08 Javascript
浅析js预加载/延迟加载
2014/09/25 Javascript
浅谈JS日期(Date)处理函数
2014/12/07 Javascript
整理Javascript流程控制语句学习笔记
2015/11/29 Javascript
封装好的javascript前端分页插件pagination
2016/01/04 Javascript
jQuery获取同级元素的简单代码
2016/07/09 Javascript
jquery判断类型是不是number类型的实例代码
2016/10/07 Javascript
jQuery实现键盘回车搜索功能
2017/07/25 jQuery
Vue.js实现大转盘抽奖总结及实现思路
2019/10/09 Javascript
Vue项目打包部署到iis服务器的配置方法
2019/10/14 Javascript
js实现滑动滑块验证登录
2020/07/24 Javascript
Python随机生成信用卡卡号的实现方法
2015/05/14 Python
Python  unittest单元测试框架的使用
2018/09/08 Python
在python里从协程返回一个值的示例
2019/02/19 Python
python使用celery实现异步任务执行的例子
2019/08/28 Python
pytorch之ImageFolder使用详解
2020/01/06 Python
python 8种必备的gui库
2020/08/27 Python
荷兰牛仔裤网上商店:Jeans Centre
2018/04/03 全球购物
Eclipse面试题
2014/03/22 面试题
不开辟用于交换数据的临时空间,如何完成字符串的逆序
2012/12/02 面试题
本科毕业生自我鉴定
2013/11/02 职场文书
联欢晚会主持词
2014/03/25 职场文书
纪念九一八事变演讲稿:勿忘国耻
2014/09/14 职场文书
公司合作协议范文
2014/10/01 职场文书
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
2021/04/12 Python
uniapp 微信小程序 自定义tabBar 导航
2022/04/22 Javascript
oracle delete误删除表数据后如何恢复
2022/06/28 Oracle