語言:Pythonpython
工具:MySQL,Tkinter,圖靈機器人mysql
功能:圖形聊天工具,能夠選擇自動回覆或者人工回覆。sql
注意:若是運行須要自建mysql數據庫表、還有安裝各類模塊、還有到「圖靈機器人」申請帳戶(免費),不然看看就好了。數據庫
(部分借鑑自某個博客,忘記哪裏看的了,tkinter部分和tcp鏈接都是從那裏學來的)django
一、服務器api
#filename:Server+SwitchButton.py #-*-coding:utf-8-*- import Tkinter import tkFont import socket import thread import time import urllib import urllib2 import traceback import MySQLdb import random import sys reload(sys) sys.setdefaultencoding('utf8') class Server(): title = 'Python自動客服-服務器' Ip = '127.0.0.1'#還不知怎麼用私網鏈接,目前只能用公網ip設置serverIp Port = 8808#端口必須在1024以上 global serverSock global receiveMsg global message flag = False #初始化類的相關屬性,相似於構造方法 def __init__(self): from Tkinter import * self.root = Tkinter.Tk() self.root.title(self.title) #窗口面板,用6個frame面板佈局,ip和port設置框架最後由於鏈接方式的選取問題取消 self.frame = [Tkinter.Frame(), Tkinter.Frame(), Tkinter.Frame(), Tkinter.Frame(), Tkinter.Frame(), Tkinter.Frame()] #frame0 #切換功能的checkButton self.CheckVar1 = IntVar() self.CheckVar2 = IntVar() self.CheckVar3 = IntVar() self.CheckButton1 = Checkbutton(self.frame[0], text = "手動", variable = self.CheckVar1, onvalue = 1, offvalue = 0, height=2, width = 5) self.CheckButton2 = Checkbutton(self.frame[0], text = "數據庫", variable = self.CheckVar2, onvalue = 1, offvalue = 0, height=2, width = 5) self.CheckButton3 = Checkbutton(self.frame[0], text = "圖靈", variable = self.CheckVar3, onvalue = 1, offvalue = 0, height=2, width = 5) self.CheckButton1.pack(expand=1, side=Tkinter.TOP and Tkinter.LEFT) self.CheckButton2.pack(expand=1, side=Tkinter.TOP and Tkinter.LEFT) self.CheckButton3.pack(expand=1, side=Tkinter.TOP and Tkinter.RIGHT) self.frame[0].pack(fill=Tkinter.BOTH)#expand=1, ''' #frame1 #ip地址和端口選擇,暫時取消 ft1 = tkFont.Font(family='Fixdsys', size=8) self.inputTextIp = Tkinter.Text(self.frame[1], width=20, height=2, font=ft1) self.inputTextPort = Tkinter.Text(self.frame[1], width=7, height=2, font=ft1) self.ipConfirmButton = Tkinter.Button(self.frame[1], text='確認', width=5, height=2, command=self.setIpPort) self.inputTextIp.pack(expand=1, fill=Tkinter.BOTH) self.inputTextPort.pack(expand=1, fill=Tkinter.BOTH) self.frame[1].pack(expand=1, fill=Tkinter.BOTH) ''' #frame2 #顯示消息Text右邊的滾動條 self.chatTextScrollBar = Tkinter.Scrollbar(self.frame[2]) self.chatTextScrollBar.pack(side=Tkinter.RIGHT, fill=Tkinter.Y) #顯示消息Text,並綁定上面的滾動條 #原本應該相互綁定,但實際運行時,滑動條沒有綁定列表框 self.chatText = Tkinter.Listbox(self.frame[2], width=80, height=18) self.chatText['yscrollcommand'] = self.chatTextScrollBar.set self.chatText.pack(expand=1, side=Tkinter.LEFT, fill=Tkinter.BOTH) #self.chatTextScrollBar['command'] = self.chatText.yview() self.frame[2].pack(fill=Tkinter.BOTH) #frame3 #標籤,建立高度爲2的空白區區分ListBox和Text label = Tkinter.Label(self.frame[3], height=2) label.pack(fill=Tkinter.BOTH) self.frame[3].pack(fill=Tkinter.BOTH) #frame4 #輸入消息Text的滾動條 self.inputTextScrollBar = Tkinter.Scrollbar(self.frame[4]) self.inputTextScrollBar.pack(side=Tkinter.RIGHT, fill=Tkinter.Y) #輸入消息Text,並與滾動條綁定 #經常使用字體元組('Arial',('Courier New',),('Comic Sans MS',),'Fixdsys',('MS Sans Serif',),('MS Serif',),'Symbol','System',('Times New Roman',),'Verdana') ft4 = tkFont.Font(family='Fixdays', size=11) self.inputText = Tkinter.Text(self.frame[4], width=80, height=8, font=ft4) self.inputText['yscrollcommand'] = self.inputTextScrollBar.set self.inputText.pack(expand=1, fill=Tkinter.BOTH) #self.inputTextScrollBar['command'] = self.chatText.yview() self.frame[4].pack(fill=Tkinter.BOTH) #frame5 #發送消息按鈕 self.sendButton = Tkinter.Button(self.frame[5], text=' 發 送 ', width=10, command=self.ManualMessage)#setReplyStatus)#發送按鈕的事件調用設置回覆方式函數 self.sendButton.pack(expand=1, side=Tkinter.BOTTOM and Tkinter.RIGHT, padx=25, pady=5) #關閉按鈕 self.closeButton = Tkinter.Button(self.frame[5], text=' 關 閉 ', width=10, command=self.close) self.closeButton.pack(expand=1, side=Tkinter.RIGHT, padx=25, pady=5) self.frame[5].pack(expand=1, fill=Tkinter.BOTH) ''' def showCheckButton1Varialbe(self): return self.CheckButton1.variable.get() def showCheckButton2Varialbe(self): return self.CheckButton2.variable.get() ''' #接收消息並顯示 def receiveMessage(self): global receiveMsg #創建Socket鏈接 try: self.serverSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#創建socket,參數爲ipv4,TCP,另外一個參數默認爲1. self.serverSock.bind((self.Ip, self.Port)) self.serverSock.listen(15) self.buffer = 1024 self.chatText.insert(Tkinter.END, '服務器已經就緒......') except: self.flag = False self.chatText.insert(Tkinter.END,'服務器端創建鏈接錯誤,請檢查端口和ip是否可用......') try: while True: #循環接受客戶端的鏈接請求 self.connection, self.address = self.serverSock.accept() self.flag = True while True: #循環接收客戶端發送的消息 self.clientMsg = self.connection.recv(self.buffer) if not self.clientMsg: #當接受到的clientMsg爲空就跳出循環,出現過卡死狀態 continue #能夠講下三次握手:客-》服;服-》客;客-》服 elif self.clientMsg == 'Y': self.chatText.insert(Tkinter.END, '服務器端已經與客戶端創建鏈接......') self.connection.send('Y') elif self.clientMsg == 'N': self.chatText.insert(Tkinter.END, '服務器端與客戶端創建鏈接失敗......') self.connection.send('N') else: theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '客戶端 ' + theTime + ' 說:\n') self.chatText.insert(Tkinter.END, ' ' + self.clientMsg) #self.chatText.insert(Tkinter.END, type(self.clientMsg)) try: receiveMsg = self.clientMsg except: print "Error" try: self.setReplyStatus() except: self.chatText.insert(Tkinter.END, '回覆方式函數錯誤......') except: self.chatText.insert(Tkinter.END, '鏈接錯誤......') #判斷回覆方式 def setReplyStatus(self): global replyStatus global receiveMsg #regard the num as 4,2,1,and add it to replyStatus if self.CheckVar1.get()==1 and self.CheckVar2.get()==0 and self.CheckVar3.get()==0: self.replyStatus=7 #此處刪除函數的緣由是,已經設計「發送」按鈕的command調用了ManualMessage,因此在此處定義則調用了兩次函數,而這裏的這個返回空 #self.ManualMessage() #數據庫回覆 elif self.CheckVar1.get()==0 and self.CheckVar2.get()==1 and self.CheckVar3.get()==0: self.replyStatus=2 try: dataInfo=self.DatabaseInformation() print "dataInfo:",dataInfo #輸入hi時,下面的語句訪問錯誤 try: self.DatabaseQuestion() except: print "hahe181" print "dataQues:",dataQues if dataInfo==None and dataQues is not None: self.DatabaseQuestion() elif dataInfo==None and dataQues==None: self.chatText.insert(Tkinter.END, '沒法匹配數據庫信息,請手動回覆') self.ManualMessage() elif dataInfo is not None and dataQues is None: self.DatabaseInformation() #默認兩表不存在交集,因此這部分爲空 else: pass except: pass#self.chatText.insert(Tkinter.END, '數據庫回覆錯誤') elif self.CheckVar1.get()==0 and self.CheckVar2.get()==0 and self.CheckVar3.get()==1: self.replyStatus=1 self.TuringMessage() #數據庫+圖靈回覆 elif self.CheckVar2.get()==1 and self.CheckVar3.get()==1: self.reply=3 try: self.DatabaseInformation() if self.DatabaseInformation()==None: self.DatabaseQuestion() if self.DatabaseQuestion()==None: self.TuringMessage() if self.TuringMessage()==None: self.chatText.insert(Tkinter.END, '沒法匹配數據庫信息,請手動回覆') self.ManualMessage() else: self.DatabaseQuestion() else: self.DatabaseInformation() except: self.chatText.insert(Tkinter.END, '數據庫+圖靈回覆錯誤') elif self.CheckVar1.get()==1 and self.CheckVar2.get()==0 and self.CheckVar3.get()==1: self.replyStatus=1 self.TuringMessage() elif self.CheckVar1.get()==1 and self.CheckVar2.get()==1 and self.CheckVar3.get()==0: self.replyStatus=2 self.DatabaseInformation() self.DatabaseQuestion() else: #格式化當前的時間 theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END,' ' + '請選擇一種回覆方式,選擇兩種以上都變爲數據庫和圖靈自動回覆(目前狀態)' + '\n') #自動切換爲011或者111狀態 ''' #爲何這個也錯?暫時放棄 self.CheckVar2.get()==1 self.CheckVar3.get()==1 self.setReplyStatus() ''' ''' #爲何提示database()訪問有誤,global receiveMsg沒有定義? self.reply=3 if self.DatabaseMessage()==None: if self.TuringMessage()==None: theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END,' ' + '未能成功匹配,請手動輸入回覆信息' + '\n') self.ManualMessage() else: self.TuringMessage() else: self.DatabaseMessage() ''' ''' #經過判斷回覆方式獲得將要執行的回覆語句,並由此改變replyStatus的值,再由此函數充當此button的commond函數。暫時放棄。 def setSendButtonStyle(self): if self.replyStatus==7: self.ManualMessage() elif self.replyStatus==: self.ManualMessage() ''' #獲取圖靈消息 def TuringMessage(self): #try: #抓取turing的回覆 global receiveMsg global string #self.chatText.insert(Tkinter.END, "Hello, I'm Turing. Enter bye to quit.") TuringQuestion = receiveMsg.encode('utf-8')#.decode('gb18030') try: TuringQ = "http://www.tuling123.com/openapi/api?key=dcc40d6323b576076c3005043aaba756&info=%s" %(TuringQuestion) except: self.chatText.insert(Tkinter.END, "沒法訪問圖靈數據庫1,暫時將調用手動回覆,請輸入......") self.manualMessage() #print 11111 try: TuringRequest = urllib2.Request(TuringQ) print 11111 except: self.chatText.insert(Tkinter.END, "圖靈數據庫提交數據出錯2,暫時將調用手動回覆,請輸入......") self.manualMessage() #print 22222 try: TuringResponse = urllib2.urlopen(TuringRequest) print 22222 except: self.chatText.insert(Tkinter.END, "獲取圖靈數據庫數據錯誤3,暫時將調用手動回覆,請輸入......") self.manualMessage() TuringAnswer= TuringResponse.read().decode('utf-8')#.encode('gb18030') #print 33333 try: #從圖靈獲取的數據是字符串(字典格式的),轉化成字典,並提取text對應的字符串 string = eval(TuringAnswer)["text"] print 33333 except: self.chatText.insert(Tkinter.END, "圖靈數據庫數據轉換錯誤4,沒法輸出,暫時將調用手動回覆,請輸入......") self.manualMessage() #print 44444 #if self.flag == True: theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END,' ' + string + '\n') if self.flag == True: self.connection.send(string) else: self.chatText.insert(Tkinter.END,'您還未與客戶端創建鏈接,客戶端沒法收到您的消息\n') #except: #return None #獲取手動輸入信息 def ManualMessage(self): message = self.inputText.get('1.0',Tkinter.END) #格式化當前的時間 theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END,' ' + message + '\n') if self.flag == True: #將消息發送到客戶端 self.connection.send(message) else: #Socket鏈接沒有創建,提示用戶 self.chatText.insert(Tkinter.END,'您還未與客戶端創建鏈接,客戶端沒法收到您的消息\n') #清空用戶在Text中輸入的消息 self.inputText.delete(0.0,message.__len__()-1.0) ''' #手動回覆信息,獲得用戶在Text中輸入的消息 #這個1.0使得get兩次,第一次是未輸入的狀況,get了空,第二次get了輸入的字符串 string = self.inputText.get('1.0',Tkinter.END) print "string:",string if string is None: pass elif self.flag == True and string is not None: theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') print 112 self.chatText.insert(Tkinter.END,string) print 123 self.connection.send(string) print 124 else: self.chatText.insert(Tkinter.END,'您還未與客戶端創建鏈接,客戶端沒法收到您的消息\n') #清空用戶在Text中輸入的消息 self.inputText.delete(0.0,message.__len__()-1.0) ''' #-------------------------------------------------------------- #數據庫回覆對話信息 def DatabaseQuestion(self): global string try: #問題出在receiveMsg上!!! print 1 global receiveMsg print receiveMsg.strip() try: conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='n5252n59',db='python',charset='utf8') except: self.chatText.insert(Tkinter.END, "數據庫鏈接錯誤,請檢查數據庫配置") with conn: cur = conn.cursor() sql = "SELECT * from QuestionAnswerInformation WHERE Question LIKE %s" #最痛苦的原來是receiveMsg左右各有一個空格,使用strip()消去,就成了正常字符串 cur.execute(sql,(receiveMsg.strip(),)) try: pass #cur.execute(sql,(receiveMsg,)) #self.chatText.insert(Tkinter.END, "ha311") except: self.chatText.insert(Tkinter.END, "數據庫語句載入錯誤,請檢查數據庫配置") try: results=cur.fetchall() #!!!這裏返回爲空!!!??? #print 'results:',results except: self.chatText.insert(Tkinter.END, "fetch Error 317") try: question=results[0][1] except: #!!!這句在輸入信息查詢時會輸出,報錯??? #self.chatText.insert(Tkinter.END, "fetch Error 362") pass #self.chatText.insert(Tkinter.END, question) #print question answer=results[0][2] #self.chatText.insert(Tkinter.END, answer) #print "answer:",answer LinkToNum=results[0][3] #print "LinkToNum:",LinkToNum LinkToString=results[0][4] #print "LinkToString:",LinkToString cur.close() ''' #載入隨機數,判斷經過本詞條回覆,仍是類似詞條(可連接到的)回覆 randomReply=random.randrange(0,2) #print randomReply if randomReply is not 0 and answer is not None: string = "%s:%s。" %(question,answer) print string else: ''' #!!!3個數據8種回覆方式 #(任,空,空)當首次查詢的結果爲空時,建立另外一個遊標,獲取linkToNum,並經過Num查找連接向的詞條 if LinkToNum is None and LinkToString is None: #!!!這裏須要對確切信息和類似信息坐下處理(LIKE和=的區別) #string = "%s:%s。" %(question,answer) #print "您想問的是這個嗎?" if answer is not None: string = "%s。" %(answer) theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END, string) else: self.chatText.insert(Tkinter.END, "return None from the database,Please use the ManualMessage") #(任,非,非) elif LinkToNum is not None and LinkToString is not None: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,不建議連接到字符串和連接到編號同時存在,請檢查數據庫") #(任,非,空) elif LinkToNum is not None and LinkToString is None: if answer is None: #直接查找連接到的詞條,和下面else後的代碼同樣,可是寫函數就不方便了,因此寫兩個 try: curNum = conn.cursor() sqlLinkToNum = "SELECT * from QuestionAnswerInformation WHERE Num = %s" except: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫1") try: curNum.execute(sqlLinkToNum,(LinkToNum,)) except: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫2") try: resultsNum=curNum.fetchall() string = "%s:%s。" %(resultsNum[0][1],resultsNum[0][2]) if resultsNum[0][2] is not None: theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END, "您想問的是這個嗎?") self.chatText.insert(Tkinter.END, string) else: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫3") except: self.chatText.insert(Tkinter.END, "return None from the database,Please use the ManualMessage") curNum.close() elif answer is not None: #(非,非,空)(用例是輸入hi)載入隨機數,判斷經過本詞條回覆,仍是類似詞條(可連接到的)回覆 randomReply=random.randrange(0,2) #曾經隨機數出過問題,經過print檢驗沒有問題啊 #print randomReply if randomReply is not 0: #string = "%s:%s。" %(question,answer) string = "%s。" %(answer) theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END, string) else: #執行LinkToNum連接到的詞條 try: curNum = conn.cursor() sqlLinkToNum = "SELECT * from QuestionAnswerInformation WHERE Num = %s" except: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫1") try: curNum.execute(sqlLinkToNum,(LinkToNum,)) except: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫2") try: resultsNum=curNum.fetchall() string = "%s。" %(resultsNum[0][2]) #string = "%s:%s。" %(resultsNum[0][1],resultsNum[0][2]) if resultsNum[0][2] is not None: #print "您想問的是這個嗎?" self.chatText.insert(Tkinter.END, string) else: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫3") except: self.chatText.insert(Tkinter.END, "return None from the database,Please use the ManualMessage") curNum.close() #(任,空,非)連接到字符串 elif LinkToNum is None and LinkToString is not None: if answer is None: try: curString = conn.cursor() sqlLinkToString = "SELECT * from QuestionAnswerInformation WHERE Question = %s" except: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫1") curString.execute(sqlLinkToString,(LinkToString,)) try: resultsString=curString.fetchall() string = "%s:%s。" %(resultsString[0][1],resultsString[0][2]) if resultsString[0][2] is not None: theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END, "您想問的是這個嗎?") self.chatText.insert(Tkinter.END, string) else: self.chatText.insert(Tkinter.END, "return None from the database,Please use the ManualMessage") except: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫2") curString.close() elif answer is not None: randomReply=random.randrange(0,2) #print randomReply if randomReply is not 0: #string = "%s:%s。" %(question,answer) string = "%s。" %(answer) theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END, string) else: try: curString = conn.cursor() sqlLinkToString = "SELECT * from QuestionAnswerInformation WHERE Question = %s" except: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫1") try: curString.execute(sqlLinkToString,(LinkToString,)) except: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫2") try: resultsString=curString.fetchall() string = "%s:%s。" %(resultsString[0][1],resultsString[0][2]) except: self.chatText.insert(Tkinter.END, "數據庫信息輸出錯誤,請檢查數據庫3") if answer is not None: theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END, "您想問的是這個嗎?") self.chatText.insert(Tkinter.END, string) curString.close() else: self.chatText.insert(Tkinter.END, "return None from the database,Please use the ManualMessage") curString.close() #默認linkToString和LinkToNum不能同時不爲空,能夠同時爲空,或者一個爲空 #if self.flag == True and string is not None: if string is not None: self.connection.send(string) #return string else: self.chatText.insert(Tkinter.END,'您還未與客戶端創建鏈接,客戶端沒法收到您的消息\n') except: return None #-------------------------------------------------------------- #數據庫回覆商品信息 def DatabaseInformation(self): ''' global receiveMsg print receiveMsg.strip() try: conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='n5252n59',db='python',charset='utf8') except: self.chatText.insert(Tkinter.END, "數據庫鏈接錯誤,請檢查數據庫配置") with conn: cur = conn.cursor() sql = "SELECT * from QuestionAnswerInformation WHERE Question LIKE %s" #最痛苦的原來是receiveMsg左右各有一個空格,使用strip()消去,就成了正常字符串 cur.execute(sql,(receiveMsg.strip(),)) try: pass #cur.execute(sql,(receiveMsg,)) #self.chatText.insert(Tkinter.END, "ha311") except: self.chatText.insert(Tkinter.END, "數據庫語句載入錯誤,請檢查數據庫配置") try: results=cur.fetchall() #!!!這裏返回爲空!!!??? print 'results:',results ''' #import MySQLdb try: global receiveMsg #print "receiveMsg:",receiveMsg #print "receiveMsg.strip():",receiveMsg.strip() #global message #theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) #self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') try: conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='n5252n59',db='python',charset='utf8') except: self.chatText.insert(Tkinter.END, "數據庫鏈接錯誤,請檢查數據庫配置") with conn: cur = conn.cursor() sql="SELECT * from LeatherShoesInformation WHERE ShoesName LIKE %s" cur.execute(sql,(receiveMsg.strip(),)) try: results=cur.fetchall() print results except: print "error" #cur.execute(sql,(receiveMsg,)) #lineNum = int(cur.rowcount) #databaseReturn = cur.fetchone()[lineNum-1] #print databaseReturn string1 = "我猜,您正考慮的就是這款皮鞋吧:" string2 = "%s,原價:%s,打折後只有:%s。" %(results[0][2],results[0][3],results[0][4]) string3 = "這款鞋是(%s),(%s)的。" %(results[0][7],results[0][8]) string4 = "另外,這款鞋是賣家評價%s,%s的優質皮鞋。" %(results[0][12],results[0][10]) string5 = "若是您想購買這雙皮鞋,咱們還將贈送您%s。咱們建議您,%s。" %(results[0][11],results[0][13]) string = string1+string2+string3+string4+string5 theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END,string1) self.chatText.insert(Tkinter.END,string2) self.chatText.insert(Tkinter.END,string3) self.chatText.insert(Tkinter.END,string4) self.chatText.insert(Tkinter.END,string5) cur.close() #if self.flag == True: #self.sendMessage() #這一行若是調用sendMessage(),將只輸出一行 if self.flag == True: self.connection.send(string) else: self.chatText.insert(Tkinter.END,'您還未與客戶端創建鏈接,客戶端沒法收到您的消息\n') #self.connection.send(string2) #self.connection.send(string3) #self.connection.send(string4) #self.connection.send(string5) except: return #6月7日決定註銷這段代碼,將輸出放在函數中進行 #發送消息,只供manual和turing調用,database的發送方式還沒定 ''' def sendMessage(self): global message theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END,' ' + message + '\n') if self.flag == True: self.connection.send(message) else: self.chatText.insert(Tkinter.END,'您還未與客戶端創建鏈接,客戶端沒法收到您的消息\n') ''' #關閉消息窗口並退出 def close(self): sys.exit() #啓動線程接收客戶端的消息 def startNewThread(self): #啓動一個新線程來接收客戶端的消息 #thread.start_new_thread(function,args[,kwargs])函數原型, #其中function參數是將要調用的線程函數,args是傳遞給線程函數的參數,它必須是個元組類型,而kwargs是可選的參數 #receiveMessage函數不須要參數,就傳一個空元組 thread.start_new_thread(self.receiveMessage, ()) #thread.start_new_thread(self.setReplyStatus, ()) def main(): server = Server() server.startNewThread() server.setReplyStatus() server.root.mainloop() if __name__ == '__main__': main()
二、客戶端服務器
#filename:TuringTkClient.py #-*-coding:utf-8-*- # Python在線聊天客戶端 import Tkinter import tkFont import socket import thread import time import sys reload(sys); sys.setdefaultencoding('utf8'); class ClientUI(): title = 'Python自動客服-客戶端' local = '127.0.0.1' port = 8808 global clientSock; flag = False #初始化類的相關屬性,相似於構造方法 def __init__(self): self.root = Tkinter.Tk() self.root.title(self.title) #窗口面板,用4個面板佈局 self.frame = [Tkinter.Frame(),Tkinter.Frame(),Tkinter.Frame(),Tkinter.Frame()] #顯示消息Text右邊的滾動條 self.chatTextScrollBar = Tkinter.Scrollbar(self.frame[0]) self.chatTextScrollBar.pack(side=Tkinter.RIGHT,fill=Tkinter.Y) #顯示消息Text,並綁定上面的滾動條 self.chatText = Tkinter.Listbox(self.frame[0],width=80,height=18) self.chatText['yscrollcommand'] = self.chatTextScrollBar.set self.chatText.pack(expand=1,fill=Tkinter.BOTH) self.chatTextScrollBar['command'] = self.chatText.yview() self.frame[0].pack(expand=1,fill=Tkinter.BOTH) #標籤,分開消息顯示Text和消息輸入Text label = Tkinter.Label(self.frame[1],height=2) label.pack(fill=Tkinter.BOTH) self.frame[1].pack(expand=1,fill=Tkinter.BOTH) #輸入消息Text的滾動條 self.inputTextScrollBar = Tkinter.Scrollbar(self.frame[2]) self.inputTextScrollBar.pack(side=Tkinter.RIGHT,fill=Tkinter.Y) #輸入消息Text,並與滾動條綁定 ft = tkFont.Font(family='Fixdsys',size=11) self.inputText = Tkinter.Text(self.frame[2],width=80,height=8,font=ft) self.inputText['yscrollcommand'] = self.inputTextScrollBar.set self.inputText.pack(expand=1,fill=Tkinter.BOTH) self.inputTextScrollBar['command'] = self.chatText.yview() self.frame[2].pack(expand=1,fill=Tkinter.BOTH) #發送消息按鈕 self.sendButton=Tkinter.Button(self.frame[3],text=' 發 送 ',width=10,command=self.sendMessage) self.sendButton.pack(expand=1,side=Tkinter.BOTTOM and Tkinter.RIGHT,padx=15,pady=8) #關閉按鈕 self.closeButton=Tkinter.Button(self.frame[3],text=' 關 閉 ',width=10,command=self.close) self.closeButton.pack(expand=1,side=Tkinter.RIGHT,padx=15,pady=8) self.frame[3].pack(expand=1,fill=Tkinter.BOTH) #接收消息 def receiveMessage(self): try: #創建Socket鏈接 self.clientSock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) self.clientSock.connect((self.local, self.port)) self.flag = True except: self.flag = False self.chatText.insert(Tkinter.END,'您還未與服務器端創建鏈接,請檢查服務器端是否已經啓動') return self.buffer = 1024 self.clientSock.send('Y') while True: try: if self.flag == True: #鏈接創建,接收服務器端消息 self.serverMsg = self.clientSock.recv(self.buffer) if self.serverMsg == 'Y': self.chatText.insert(Tkinter.END,'客戶端已經與服務器端創建鏈接......') elif self.serverMsg == 'N': self.chatText.insert(Tkinter.END,'客戶端與服務器端創建鏈接失敗......') elif not self.serverMsg: continue else: theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '服務器 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END, ' ' + self.serverMsg) else: break except : self.chatText.insert(Tkinter.END,'出現錯誤......') self.clientSock.close() self.close() #發送消息 def sendMessage(self): #狀況1:從text_input獲取用戶輸入 #獲得用戶在Text中輸入的消息 message = self.inputText.get('1.0',Tkinter.END) #格式化當前的時間 theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.chatText.insert(Tkinter.END, '客戶端 ' + theTime +' 說:\n') self.chatText.insert(Tkinter.END,' ' + message + '\n') if self.flag == True: #將消息發送到服務器端 self.clientSock.send(message); else: #Socket鏈接沒有創建,提示用戶 self.chatText.insert(Tkinter.END,'您還未與服務器端創建鏈接,服務器端沒法收到您的消息\n') #清空用戶在Text中輸入的消息 self.inputText.delete(0.0,message.__len__()-1.0) #鏈接數據庫並操做 #def connectDatabaseRequest(self): #點擊小提示請求server鏈接數據庫 #正常打字請求server回覆 #關閉消息窗口並退出 def close(self): sys.exit() #啓動線程接收服務器端的消息 def startNewThread(self): #啓動一個新線程來接收服務器端的消息 #thread.start_new_thread(function,args[,kwargs])函數原型, #其中function參數是將要調用的線程函數,args是傳遞給線程函數的參數,它必須是個元組類型,而kwargs是可選的參數 #receiveMessage函數不須要參數,就傳一個空元組 thread.start_new_thread(self.receiveMessage,()) def main(): client = ClientUI() client.startNewThread() client.root.mainloop() if __name__=='__main__': main()
三、效果圖(好大!!!)多線程
四、缺陷:併發
不少,好比tkinter界面太糟糕,交互過程太簡潔並且不合理,沒有認證過程,沒有加入多線程併發等等一大堆問題。框架
甚至有些代碼註釋還沒改,算了,正學django,之後弄一個完整的過程吧。