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实现博客文章爬虫示例
Feb 26 Python
Python中使用装饰器来优化尾递归的示例
Jun 18 Python
Python 中urls.py:URL dispatcher(路由配置文件)详解
Mar 24 Python
Python并行分布式框架Celery详解
Oct 15 Python
利用python实现对web服务器的目录探测的方法
Feb 26 Python
Python 内置变量和函数的查看及说明介绍
Dec 25 Python
python 使用递归回溯完美解决八皇后的问题
Feb 26 Python
利用python下载scihub成文献为PDF操作
Jul 09 Python
python如何随机生成高强度密码
Aug 19 Python
Pytorch 扩展Tensor维度、压缩Tensor维度的方法
Sep 09 Python
基于python实现简单网页服务器代码实例
Sep 14 Python
Python selenium的这三种等待方式一定要会!
Jun 10 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
推荐几部必看的DC动画电影
2020/03/03 欧美动漫
通过缓存数据库结果提高PHP性能的原理介绍
2012/09/05 PHP
PHP时间戳与日期之间转换的实例介绍
2013/04/19 PHP
Thinkphp中Create方法深入探究
2014/06/16 PHP
解决PHP里大量数据循环时内存耗尽的方法
2015/10/10 PHP
PHP异常类及异常处理操作实例详解
2018/12/19 PHP
广告代码静态化js通用函数
2007/05/09 Javascript
一个可以兼容IE FF的加为首页与加入收藏实现代码
2009/11/02 Javascript
表单切换,用回车键替换Tab健(不支持IE)
2011/07/20 Javascript
js中将HTMLCollection/NodeList/伪数组转换成数组的代码
2011/07/31 Javascript
html超链接打开窗口大小的方法
2013/03/05 Javascript
Javascript中的数据类型之旅
2015/10/18 Javascript
Js获取图片原始宽高的实现代码
2016/05/17 Javascript
jQuery实现手机版页面翻页效果的简单实例
2016/10/05 Javascript
js实现碰撞检测特效代码分享
2016/10/16 Javascript
Jquery EasyUI $.Parser
2017/06/02 jQuery
详解组件库的webpack构建速度优化
2018/06/18 Javascript
JavaScript面向对象中接口实现方法详解
2019/07/24 Javascript
JS扁平化输出数组的2种方法解析
2019/09/17 Javascript
github配置使用指南
2014/11/18 Python
对python中的控制条件、循环和跳出详解
2019/06/24 Python
python函数参数(必须参数、可变参数、关键字参数)
2019/08/16 Python
Python学习笔记之字符串和字符串方法实例详解
2019/08/22 Python
Django中使用Json返回数据的实现方法
2020/06/03 Python
Pycharm编辑器功能之代码折叠效果的实现代码
2020/10/15 Python
Python操作Excel的学习笔记
2021/02/18 Python
美国经典刺绣和字母儿童服装特卖:Smocked Auctions
2018/07/16 全球购物
UNDONE手表官网:世界领先的定制手表品牌
2018/11/13 全球购物
Servlet方面面试题
2016/09/28 面试题
个人实用的自我评价范文
2013/11/23 职场文书
毕业生求职找工作的自我评价范文
2013/11/27 职场文书
格列佛游记读书笔记
2015/06/30 职场文书
优秀家长事迹材料(2016推荐版)
2016/02/29 职场文书
学校就业保障协议书
2019/06/24 职场文书
Java 多态分析
2022/04/26 Java/Android
解决 redis 无法远程连接
2022/05/15 Redis