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 相关文章推荐
python中global与nonlocal比较
Nov 21 Python
Python函数中*args和**kwargs来传递变长参数的用法
Jan 26 Python
python中pandas.DataFrame对行与列求和及添加新行与列示例
Mar 12 Python
解决在pycharm中显示额外的 figure 窗口问题
Jan 15 Python
Python实现微信机器人的方法
Sep 06 Python
使用pyqt5 tablewidget 单元格设置正则表达式
Dec 13 Python
Python实现大数据收集至excel的思路详解
Jan 03 Python
如何定义TensorFlow输入节点
Jan 23 Python
python GUI库图形界面开发之PyQt5图片显示控件QPixmap详细使用方法与实例
Feb 27 Python
浅谈keras 模型用于预测时的注意事项
Jun 27 Python
python request 模块详细介绍
Nov 10 Python
Python __slots__的使用方法
Nov 15 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 adodb操作mysql数据库
2009/03/19 PHP
xss防御之php利用httponly防xss攻击
2014/03/21 PHP
Laravel多域名下字段验证的方法
2019/04/04 PHP
基于JavaScript实现 获取鼠标点击位置坐标的方法
2013/04/12 Javascript
JS检测输入字符是否包含非法字符的示例代码
2014/02/11 Javascript
js操纵dom生成下拉列表框的方法
2014/02/24 Javascript
JS获取数组最大值、最小值及长度的方法
2015/11/24 Javascript
详解Bootstrap的aria-label和aria-labelledby应用
2016/01/04 Javascript
jquery 动态增加删除行的简单实例(推荐)
2016/10/12 Javascript
简单的jQuery拖拽排序效果的实现(增强动态)
2017/02/09 Javascript
jQuery实现动态生成表格并为行绑定单击变色动作的方法
2017/04/17 jQuery
基于react组件之间的参数传递(详解)
2017/09/05 Javascript
JS获取一个表单字段中多条数据并转化为json格式
2017/10/17 Javascript
浅谈Vue.js路由管理器 Vue Router
2018/08/16 Javascript
vue基于better-scroll仿京东分类列表
2020/06/30 Javascript
在vue中使用cookie记住用户上次选择的实例(本次例子中为下拉框)
2020/09/11 Javascript
简单谈谈Python中的元祖(Tuple)和字典(Dict)
2017/04/21 Python
Python 批量合并多个txt文件的实例讲解
2018/05/08 Python
Python使用pandas对数据进行差分运算的方法
2018/12/22 Python
Django框架教程之中间件MiddleWare浅析
2019/12/29 Python
pytorch中nn.Conv1d的用法详解
2019/12/31 Python
python安装cx_Oracle和wxPython的方法
2020/09/14 Python
互斥锁解决 Python 中多线程共享全局变量的问题(推荐)
2020/09/28 Python
Sentry错误日志监控使用方法解析
2020/11/12 Python
澳大利亚儿童精品仓库:Goo & Co.
2019/06/20 全球购物
英国家具、照明、家居用品网上商店:Wayfair.co.uk
2020/02/13 全球购物
《桂林山水》教学反思
2014/02/08 职场文书
医学院毕业生自荐信范文
2014/03/06 职场文书
技术负责人任命书
2014/06/05 职场文书
小学生读书活动总结
2014/06/30 职场文书
党校学习心得体会范文
2014/09/09 职场文书
文案策划岗位职责
2015/02/11 职场文书
创先争优活动个人总结
2015/03/04 职场文书
2015年社区工作总结
2015/04/08 职场文书
2016应届毕业生自荐信范文
2016/01/28 职场文书
Spring Boot 的创建和运行示例代码详解
2022/07/23 Java/Android