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 相关文章推荐
解决windows下Sublime Text 2 运行 PyQt 不显示的方法分享
Jun 18 Python
安装dbus-python的简要教程
May 05 Python
使用python在本地电脑上快速处理数据
Jun 22 Python
详解supervisor使用教程
Nov 21 Python
浅谈Series和DataFrame中的sort_index方法
Jun 07 Python
Python 实现Windows开机运行某软件的方法
Oct 14 Python
python 运用Django 开发后台接口的实例
Dec 11 Python
Python爬虫实现获取动态gif格式搞笑图片的方法示例
Dec 24 Python
python dlib人脸识别代码实例
Apr 04 Python
pytorch查看torch.Tensor和model是否在CUDA上的实例
Jan 03 Python
如何在向量化NumPy数组上进行移动窗口
May 18 Python
深入理解python协程
Jun 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
通过ICQ网关发送手机短信的PHP源程序
2006/10/09 PHP
php Sql Server连接失败问题及解决办法
2009/08/07 PHP
php压缩多个CSS为一个css的代码并缓存
2011/04/21 PHP
php循环语句 for()与foreach()用法区别介绍
2012/09/05 PHP
php通过记录IP来防止表单重复提交方法分析
2014/12/16 PHP
PHP常见的几种攻击方式实例小结
2019/04/29 PHP
Javascript 类型转换方法
2010/10/24 Javascript
jQuery autocomplate 自扩展插件、自动完成示例代码
2011/03/28 Javascript
用js调用迅雷下载代码的二种方法
2013/04/15 Javascript
将文本输入框内容加入表中的js代码
2013/08/18 Javascript
js数组的基本用法及数组根据下标(数值或字符)移除元素
2013/10/20 Javascript
解决extjs grid 不随窗口大小自适应的改变问题
2014/01/26 Javascript
jQuery中insertBefore()方法用法实例
2015/01/08 Javascript
Javascript编程之继承实例汇总
2015/11/28 Javascript
JS实现倒计时(天数、时、分、秒)
2016/11/16 Javascript
w3c编程挑战_初级脚本算法实战篇
2017/06/23 Javascript
如何将 jQuery 从你的 Bootstrap 项目中移除(取而代之使用Vue.js)
2017/07/17 jQuery
Bootstrap与Angularjs的模态框实例代码
2017/08/03 Javascript
详解处理bootstrap4不支持远程静态框问题
2018/07/20 Javascript
layui 解决富文本框form表单提交为空的问题
2019/10/26 Javascript
python虚拟环境 virtualenv的简单使用
2020/01/21 Javascript
[44:10]2018DOTA2亚洲邀请赛 4.5 淘汰赛 EG vs VP 第一场
2018/04/06 DOTA
python使用urllib模块和pyquery实现阿里巴巴排名查询
2014/01/16 Python
python实现dnspod自动更新dns解析的方法
2014/02/14 Python
Python使用MYSQLDB实现从数据库中导出XML文件的方法
2015/05/11 Python
python开发之list操作实例分析
2016/02/22 Python
python实现三次样条插值
2018/12/17 Python
如何使用python操作vmware
2019/07/27 Python
Python Web静态服务器非堵塞模式实现方法示例
2019/11/21 Python
解决更改AUTH_USER_MODEL后出现的问题
2020/05/14 Python
UI自动化定位常用实现方法代码示例
2020/10/27 Python
python利用后缀表达式实现计算器功能
2021/02/22 Python
前台文员岗位职责
2013/12/28 职场文书
生产部厂长职位说明书
2014/03/03 职场文书
中文专业毕业生自荐信
2014/05/24 职场文书
详解Golang如何实现支持随机删除元素的堆
2022/09/23 Python