笔记-twisted-adbapi-scrapy

笔记-twisted-adbapi-scrapy-mysql

1.      异步插入mysql

在爬虫中需要insert到mysql,但有一个问题是在爬虫环境中commit的及时性与性能冲突。

一般可以在close_spider进行commit,这样做的问题是如果中途数据库崩了,数据丢失,找起来也很麻烦;

但如果在insert_db中直接加入commit,又会使程序执行变得很慢。

这里就可以使用Twisted中提供的以异步方式多线程访问数据库的模块adbapi,可以显著提供程序访问数据库的效率。

adbapi.ConnectionPool方法可以创建一个数据库连接池对象,其中包括多个连接对象,每个连接对象在独立的线程中工作。adbapi只是提供了异步访问数据库的编程框架,再其内部依然使MySQLdb这样的库访问数据库。

dbpool.runInteraction(insert_db,item)以异步方式调用insert_db函数,dbpool会选择连接池中的一个连接对象在独立线程中调用insert_db,其中参数item会被传给insert_db的第二个参数,传给insert_db的第一个参数是一个Transaction对象,其借口与Cursor对象类似,可以调用execute方法执行SQL语句,insert_db执行后,连接对象会自动调用commit方法

1.1.    代码示例

import pymysql
import pymysql.cursors
from twisted.enterprise import adbapi

# 同步插入
class ZhihuPipeline(object):
    """
   
数据保存到mysql
    同步保存
    """

   
def __init__(self, conn, cursor):
        self.conn = conn
        self.cursor =cursor

    @classmethod
    def from_settings(cls, settings):
        """

       
:param settings:
       
:return:
        """
       
db_parms = dict(
            host=settings['MYSQL_HOST'],
            user=settings['MYSQL_USER'],
            password=settings['MYSQL_PASSWORD'],
            database=settings['MYSQL_DB'],
        )

        #连接池connectionpool
       
conn = pymysql.connect( **db_parms )
        cursor = conn.cursor()
        return cls(conn, cursor)

    def process_item(self, item, spider):
        """
       
同步保存
       
:param item:
       
:param spider:
       
:return:
        """
       
insert_sql = 'insert into {}'.format()
        self.cursor.execute(inert_sql)
        self.conn.commit()

    def close_spider(self,spider):
        """
       
清理
       
:param spider:
       
:return:
        """
       
self.cursor.close()
        self.conn.close()



# 异步插入
class ZhihuPipelineTwisted(object):
    """
   
数据保存到mysql
    使用了twisted进行异步操作
    """
   
def __init__(self, dbpool):
        self.dbpool = dbpool

    @classmethod
    def from_settings(cls, settings):
        """
       
:param settings:
       
:return:
        """
       
db_parms = dict(
            host=settings['MYSQL_HOST'],
            user=settings['MYSQL_USER'],
            password=settings['MYSQL_PASSWORD'],
            database=settings['MYSQL_DB'],
            cursorclass=pymysql.cursors.DictCursor
        )

        #连接池connectionpool
       
dbpool = adbapi.ConnectionPool("pymysql", **dbparms)
        return cls(dbpool)


    def process_item(self, item, spider):
        """

       
:param item:
       
:param spider:
       
:return:
        """
       
query = self.dbpool.runInteraction(self.do_insert, item)
        query.addErrback(self.handle_error, item, spider)

    def do_insert(self, cursor, item):
        insert_sql, params = 'insert into {} ({}) values ({})'
       
cursor.execute(insert_sql, params)

    @staticmethod
    def handle_error(failure, item, spider):
        # 处理插入异常
       
print(failure)

    def close_spider(self,spider):
        """
       
提交及清理
       
:param spider:
       
:return:
        """
       
self.cursor.close()
        self.conn.close()

2.      总结

adbapi为什么性能高,有空看下它是怎么优化整个执行逻辑的。

猜你喜欢

转载自www.cnblogs.com/wodeboke-y/p/10646066.html
今日推荐