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基础教程之常用运算符
Aug 29 Python
centos 下面安装python2.7 +pip +mysqld
Nov 18 Python
Python多线程编程(五):死锁的形成
Apr 05 Python
python基础入门学习笔记(Python环境搭建)
Jan 13 Python
python如何实现int函数的方法示例
Feb 19 Python
Python基于多线程实现ping扫描功能示例
Jul 23 Python
python实现猜数游戏
Mar 27 Python
Python根据指定文件生成XML的方法
Jun 29 Python
Python实现手绘图效果实例分享
Jul 22 Python
Python爬虫之Selenium实现窗口截图
Dec 04 Python
python3 删除所有自定义变量的操作
Apr 08 Python
Python实现灰色关联分析与结果可视化的详细代码
Mar 25 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安装全攻略:APACHE
2006/10/09 PHP
检查php文件中是否含有bom的函数
2012/05/31 PHP
编译PHP报错configure error Cannot find libmysqlclient under usr的解决方法
2014/06/27 PHP
php格式化json函数示例代码
2016/05/12 PHP
PhpStorm terminal无法输入命令的解决方法
2016/10/09 PHP
Alliance vs AM BO3 第二场2.13
2021/03/10 DOTA
超级强大的表单验证
2006/06/26 Javascript
JQuery的一些小应用收集
2010/03/27 Javascript
Extjs4 GridPanel 的几种样式使用介绍
2013/04/18 Javascript
浅析js中2个等号与3个等号的区别
2013/08/06 Javascript
JQuery操作三大控件(下拉,单选,复选)的方法
2013/08/06 Javascript
封装了一个支持匿名函数的Javascript事件监听器
2014/06/05 Javascript
Javascript+CSS实现影像卷帘效果思路及代码
2014/10/20 Javascript
jquery设置表单元素为不可用的简单代码
2016/07/04 Javascript
easyui form validate总是返回false的原因及解决方法
2016/11/07 Javascript
基于javascript实现按圆形排列DIV元素(二)
2016/12/02 Javascript
利用JS实现页面删除并重新排序功能
2016/12/09 Javascript
微信小程序 MD5加密登录密码详解及实例代码
2017/01/12 Javascript
Vue CLI2升级至Vue CLI3的方法步骤
2019/05/20 Javascript
[51:10]VP vs VGJ.S 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python的lambda匿名函数的简单介绍
2013/04/25 Python
python实现倒计时的示例
2014/02/14 Python
Python中使用platform模块获取系统信息的用法教程
2016/07/08 Python
详解python里使用正则表达式的全匹配功能
2017/10/19 Python
python之django母板页面的使用
2018/07/03 Python
Python join()函数原理及使用方法
2020/11/14 Python
python 爬取腾讯视频评论的实现步骤
2021/02/18 Python
Maisons du Monde德国:法国家具和装饰的市场领导者
2019/07/26 全球购物
如何写出高质量、高性能的MySQL查询
2014/11/17 面试题
移动通信行业实习自我鉴定
2013/09/28 职场文书
咖啡厅商业计划书
2014/09/15 职场文书
2015年宣传部工作总结范文
2015/03/31 职场文书
鲁滨孙漂流记读书笔记
2015/06/30 职场文书
详解MySQL 用户权限管理
2021/04/20 MySQL
goland 清除所有的默认设置操作
2021/04/28 Golang
golang 实现两个结构体复制字段
2021/04/28 Golang