Demo entry 6747594

数据存储部分

   

Submitted by 赵匡是 on Jun 04, 2018 at 13:00
Language: Python. Code size: 10.5 kB.

# _*_ coding: utf-8 _*_
#!/usr/local/bin/python2.7
'''
db_interface 是程序的mysql数据库接口,封装了一系列后续操作需要用到的数据库访问的方法。

Created on 2018年5月10日

@author: 赵匡是
'''

import mysql.connector
import re
import datetime


class DBConnector(object):
    '''
     :key: 初始化数据库连接
    '''
    def __init__(self, config=None):
        #获得连接的数据库的信息,默认连接阿里云的自有服务器。
        print ('>>>正在初始化数据库配置信息...')
        if config is None:
            print ('>>>检测到您使用默认配置')
            self._config={
            'host':'106.14.200.26',
            'port':3306,
            'user':'zhaokuangshi',
            'password':'ZhAoKuAnGsHi-2018-',
            'database':'inter_inno',
            'charset':'utf8'
            }
        else:
            print ('>>>检测到您使用自定义配置信息。')
            self._config=config
        print ('>>>数据库配置已保存!')
        print ('[成功]')
        print ('====================')
        
        #检查数据库是否已经初始化,如果没有,则进行初始化。
        self.db_init()
      
    def db_connect(self):
        '''
         :key: 连接数据库
        '''
        print ('>>>正在连接数据库...')
        try:
            #连接数据库
            self.con = mysql.connector.connect(**self._config)
            self.cursor = self.con.cursor()
            print ('[成功]')
            print ('====================')
        except mysql.connector.Error:
            print('[错误]  无法连接数据库!')

    def db_disconnect(self):
        '''
         :key: 断开数据库连接
        '''
        print ('>>>正在断开数据库连接...')
        try:
            #关闭
            self.cursor.close()
            self.con.close()
            print ('[成功]')
            print ('====================')
        except mysql.connector.Error:
            print('[错误]  无法断开数据库连接!')
        
        
        
    def db_init(self):
        '''
        :key: 检测该数据库是否已经被初始化,如果没有,则进行初始化。
        '''
        self.db_connect()
        print ('>>>正在初始化数据库...')
        try:
            print ('>>>初始化user表')
            self.cursor.execute("CREATE TABLE IF NOT EXISTS user( userID INT(11) NOT NULL auto_increment,userName VARCHAR(255) NOT NULL, sourceSite TEXT NOT NULL, level INT(11) NOT NULL, PRIMARY KEY (userID));")
            print ('>>>初始化post表')
            self.cursor.execute("CREATE TABLE IF NOT EXISTS post(postID INT(11) NOT NULL, replyID INT(11) NOT NULL, postTitle VARCHAR(255) NOT NULL, postContent TEXT, sourceURL TEXT NOT NULL, author INT(11) NOT NULL, words_count INT(11), words_split TEXT, isBest TINYINT(1) NOT NULL, date DATE NOT NULL, source_forum VARCHAR(255) NOT NULL, PRIMARY KEY (postID, replyID), FOREIGN KEY (author) REFERENCES user(userID));")
            print ('>>>初始化topic表')
            self.cursor.execute("CREATE TABLE IF NOT EXISTS topic(topicID INT(11) NOT NULL auto_increment, topicName VARCHAR(255) NOT NULL UNIQUE, PRIMARY KEY (topicID));")
            print ('>>>初始化word表')
            self.cursor.execute("CREATE TABLE IF NOT EXISTS word(wordID INT(11) NOT NULL auto_increment, word VARCHAR(255) NOT NULL UNIQUE, PRIMARY KEY(wordID));")
            print ('>>>初始化wordmap表')
            self.cursor.execute("CREATE TABLE IF NOT EXISTS wordmap(postID INT(11) NOT NULL, replyID INT(11) NOT NULL, wordmap TEXT NOT NULL, PRIMARY KEY(postID, replyID);")
            print ('>>>初始化post2word表')
            self.cursor.execute("CREATE TABLE IF NOT EXISTS post2word(postID INT(11) NOT NULL, replyID INT(11) NOT NULL, wordRank INT(11) NOT NULL auto_increment, wordID INT(11), PRIMARY KEY(postID, replyID), FOREIGN KEY (wordID) REFERENCES word(wordID));")
            print ('>>>初始化post2topic表')
            self.cursor.execute("CREATE TABLE IF NOT EXISTS post2topic(postID INT(11) NOT NULL, replyID INT(11) NOT NULL, topicID INT(11) NOT NULL, theta INT(11), nd INT(11), PRIMARY KEY (postID, replyID, topicID), FOREIGN KEY (postID, replyID) REFERENCES post(postID, replyID), FOREIGN KEY (topicID) REFERENCES topic(topicID));")
            print ('>>>初始化topic2word表')
            self.cursor.execute("CREATE TABLE IF NOT EXISTS topic2word(topicID INT(11) NOT NULL, wordID INT(11) NOT NULL, phi INT(11), nw INT(11), PRIMARY KEY (topicID, wordID), FOREIGN KEY (topicID) REFERENCES topic(topicID), FOREIGN KEY (wordID) REFERENCES word(wordID));")
            self.con.commit()
            print ('[成功]')
            print ('====================')
        except mysql.connector.Error:
            self.con.rollback()
            print('[错误]  无法初始化数据表!')
        finally:
            self.db_disconnect()
    
    def save_post(self, userName, sourceURL, replyID, postTitle, postContent, isBest, date_year, date_month, date_day, source_forum, level):
        '''
        :key: 负责存取爬虫获得的post数据。主要运行逻辑为:
            :1. 接受userName、sourceURL、postID、replyID、postTitle、postContent、isBest
            :2. 通过userName和sourceSite,去user表中查找,是否存在这个userID。如果存在,返回一个userID,如果不存在,创建一个再返回userID。
            :3. 查重,是不是相关的帖子已经被存过。(是否存在同URL、同楼层的帖子)
            :4. 存入postID、replyID、postTitle、postContent、sourceURL、author信息。
            :5. 回到用户表中,为其发帖数或回帖数(+1),判断是否为精华帖(+1)。
        '''
        date = datetime.date(date_year, date_month, date_day)
        print('>>> 正在查询原网站')
        sourceSite = self.URL2site(sourceURL)
        print '[成功] 原网站是', sourceSite
        print ('====================')
        print('>>> 正在查询用户')
        userID = self.search_user(userName, sourceSite, level)
        author = userID
        print('[成功]')
        print ('====================')
        print('>>> 正在查重')
        postID, hasReply = self.dupli_check(sourceURL, replyID)
        if postID == 0:
            print(' >>>没有重复,正在插入本条...')
            try:
#                 这里是第四步了,注意postID需要靠查询数据库中最大的postID再加一才能获得。
                #先查询最大的postID
                self.cursor.execute('SELECT MAX(postID) FROM post;')
                result = self.cursor.fetchall()
                prepostID= result[0][0]
                if prepostID is None:
                    postID = 1
                else:
                    postID = prepostID + 1
                print '[成功]postID为', postID
                print('====================')
            except mysql.connector.Error:
                print('[错误]  数据库错误!')
        elif hasReply == True:
                print('  这条数据已经有了哦!')
                return
        
        try:
            print '>>>正在存储本条帖子/回复,来自《', postTitle, '》的第', (replyID-1), '条回复...'
            print (postID, replyID, postTitle, postContent, sourceURL, author, isBest, date.isoformat(), source_forum)
            self.cursor.execute("INSERT INTO post (postID,replyID, postTitle, postContent, sourceURL, author, isBest, date, source_forum) values (%d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s')"% (postID, replyID, postTitle, postContent, sourceURL, author, isBest, date.isoformat(), source_forum))
            self.con.commit()
            

        except mysql.connector.Error:
            print('[错误]  数据库错误!')
            
    #!----------------------  辅助函数  ----------------------
    def search_user(self, userName, sourceSite, level):
        '''
         :key: 负责查询用户,如果存在则返回userID,如果不存在则添加用户。添加的时候发帖数回帖数都存0.
        '''
        userID = 0
        print '>>> 正在查询用户 ', userName, ' ...'
        self.cursor.execute('SELECT userID FROM user WHERE userName = %s AND sourceSite = %s;', (userName, sourceSite))
        result = self.cursor.fetchall()
        #如果没有则创建
        if len(result) == 0:
            print '      不存在用户 ', userName, ' ,正在创建...'
            try:
                print("INSERT INTO user (userName, sourceSite, level) VALUES ('%s', '%s',%d);" %(userName, sourceSite, level))
                self.cursor.execute("INSERT INTO user (userName, sourceSite,level) VALUES ('%s', '%s',%d);"%(userName, sourceSite, level))
                self.con.commit()
                print('[成功]')
                print('====================')
                try:
                    print '>>> 重新查询用户 ', userName, ' ...'
                    self.cursor.execute('SELECT userID FROM user WHERE userName = %s AND sourceSite = %s;', (userName, sourceSite))
                    value = self.cursor.fetchall()
                    userID = value[0][0]
                    print '[成功]UserID为',userID
                    print('====================')
                except  mysql.connector.Error:
                    print('[错误] 重新查询新用户失败!')
            except  mysql.connector.Error:
                self.con.rollback()
                print('[错误] 无法添加新用户!')
        else:
            print  '    存在用户 ', userName
            userID = result[0][0]
            print '[成功]UserID为',userID
        return userID

    def URL2site(self, sourceURL):
        '''
         :key: 将接收到的URL转换为网站名。通过正则匹配来配对。
            包含:汽车之家、爱卡汽车、易车网。
        '''
        # 正则匹配部分
        if re.search('autohome.com.cn', sourceURL, re.I):
            sourceSite = 'autohome'
        elif re.search('xcar.com.cn', sourceURL, re.I):
            sourceSite = 'xcar'
        elif re.search('bitauto.com', sourceURL , re.I):
            sourceSite = 'bitauto'
        else:
            sourceSite = None
        return sourceSite
    
    def dupli_check(self, sourceURL, replyID):
        '''
        :key: 通过sourceURL和replyID对收集的帖子查重。三种结果:①帖子全新,没有重复,直接新建;②帖子存在了,但是这条回复是新的,在以后的postID里面插入新的reply;③帖子和这条回复都是已经存在的。
        :return: 返回两个值,其中第一个整型值代表其存在的postID,如果不存在则为0;第二个代表其reply是否已经存在的boolean值。
        '''
        postID = 0
        hasReply = False
        try:

            print('>>>正在查询本帖是否存在...')
            self.cursor.execute("SELECT postID FROM post WHERE sourceURL = '%s';"% (sourceURL,))#这里只有sourceURL传入,因为如果一起传入replyID的话会让本存在的帖子(但不存在本回复)显示NULL。但是只传入sourceURL会返回多个结果或者NULL,我们需要先判断是否为NULL,如果不是,只取第0个结果。
            result = self.cursor.fetchall()
            if len(result)==0:
                print('[成功]不存在')
            else:
                print('[成功]存在')
                postID = result[0][0]
                print('>>>正在查询本回复是否存在...')
                self.cursor.execute("SELECT replyID FROM post WHERE sourceURL = '%s' AND replyID = '%s';"% (sourceURL, replyID))
                result = self.cursor.fetchall()
                if len(result)==0:
                    print('[成功]不存在')
                else:
                    print('[成功]存在')
                    hasReply = True
        except mysql.connector.Error:
            print('[错误]  数据库错误!')
        finally:
            return postID,hasReply

This snippet took 0.01 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).