使用Python實現電子詞典
阿新 • • 發佈:2018-12-12
專案內容:
一、功能說明:
1.使用者可以登入和註冊 登入憑藉使用者名稱密碼即可 註冊要求使用者必須填寫使用者名稱和密碼其他內容可自定 使用者名稱要求不能夠重複 2.使用者資料要求使用資料庫長期儲存 資料表自定 3.能夠滿足多個使用者同時登陸操作的需求(多程序多執行緒) 4.功能分為客戶端和服務端,客戶端主要發起請求,服務端處理請求,使用者啟動客戶端即進入一級介面 一級介面的功能有:登陸、註冊、退出 5.使用者登陸後即進入二級介面 二級介面內容有:查單詞 檢視歷史記錄 退出 dict.txt--》每行一個單詞 單詞和解釋之間一定有空格 後面的單詞一定比前面的大 查單詞:輸入單詞,顯示單詞意思,可以迴圈查詢,輸入##表示退出查詞 檢視歷史記錄:檢視當前使用者的歷史查詞記錄 name word time 退出:退出到一級介面,相當於登出
二、專案分析
1.確定技術點 什麼併發,什麼套接字,什麼資料庫, 檔案處理還是資料庫查詢,如果是資料庫查詢如何將單詞存入資料庫 2.建立資料表 建立幾個表 每個表結構 表關係 3 使用者資訊 歷史記錄 存單詞 註冊 查詢歷史記錄 查單詞 登入 查單詞 3.專案分析 伺服器 : 登入 註冊 查詞 歷史記錄 客戶端 : 列印介面 發出請求 接收反饋 列印結果 技術點 : 併發 sys.fork 套接字 tcp 套接字 資料庫 mysql 查詞 文字 4.搭建通訊框架 工作流程: 建立資料庫,儲存資料 ---》 搭建通訊框架, 建立併發關係---》實現具體功能封裝
三、實現
1.建立資料庫(使用mysql資料庫) mysql> create database dict default charset=utf8; mysql> use dict; Database changed // 使用者資訊表 mysql> create table user( -> id int primary key auto_increment, -> name varchar(32) not null, -> passwd varchar(16) default '000000'); //歷史記錄表 mysql> create table hist( -> id int primary key auto_increment, -> name varchar(32) not null, -> word varchar(32) not null, -> time varchar(64)); //單詞表 //text型別是文字型別,相當於字串一種,比字串大 mysql> create table words( -> id int primary key auto_increment, -> word varchar(32) not null, -> interpret text not null); 2.搭建基本框架 伺服器 建立套接字 --> 建立父子程序 --> 子程序等待處理客戶端請求 --> 父程序繼續接收下一個客戶端連線 客戶端 建立套接字 --> 發起連線請求 --> 進入一級介面 --> 請求(登入,註冊,退出) --> 登入成功進入二級介面 --> 請求(查詞,歷史記錄) 3.功能實現: (1)註冊 客戶端: 1.輸入註冊資訊 cookie getpass模組:可以隱藏密碼 getpass.getpass() 2.將註冊資訊傳送給伺服器 3.得到伺服器反饋 服務端: 1.接收請求 2.判斷是否允許註冊 3.將結果反饋給客戶端 4.註冊資訊插入資料庫 (2)登入 客戶端: 1.輸入登入資訊 2.將登入資訊傳送給伺服器 3.得到伺服器的反饋 服務端: 1.接收請求 2.判斷是否可以登入 3.將結果反饋給客戶端 (3)查單詞 客戶端: 1.輸入單詞 2.將單詞傳給伺服器 3.得到伺服器的反饋 服務端: 1.接收請求 2.判斷是否存在這個單詞 3.將結果反饋給客戶端 4.將查詢的資訊插入到資料庫 (4)查詢歷史記錄 客戶端: 1.傳送請求 2.將請求傳給伺服器 3.得到伺服器的反饋 服務端: 1.接收請求 2.判斷該使用者是否存在歷史記錄 3.將結果反饋給客戶端
四、程式碼 1.將本地檔案dict.txt中的單詞資訊新增到資料庫
import pymysql
import re
f = open('dict.txt')
db = pymysql.connect("localhost", "root", "123456", "dict")
cursor = db.cursor()
for line in f:
L = re.split(r"\s\s\s+", line)
word = L[0]
interpret = ' '.join(L[1:])
sql = "insert into words (word,interpret) values('%s','%s')" % (word, interpret)
try:
cursor.execute(sql)
db.commit()
except Exception:
db.rollback()
f.close()
2.客戶端實現功能
#!/usr/bin/python
# coding=utf-8
from socket import *
import sys
import getpass
#二級登入介面
def login(s, name):
while True:
print('''
==========查詢介面============
--1.查詢 2.歷史記錄 3.退出--
==============================
''')
try:
cmd = int(input("輸入選項>>"))
except Exception:
print("命令錯誤")
continue
if cmd not in [1, 2, 3]:
print("請輸入正確選項")
sys.stdin.flush() # 清除標準輸入
continue
elif cmd == 1:
do_query(s, name)
elif cmd == 2:
do_hist(s, name)
elif cmd == 3:
print("使用者退出")
return
#客戶端-->查單詞
def do_query(s, name):
while True:
word = input("請輸入要查詢的單詞:")
if word == '##':
break
msg = 'Q {} {}'.format(name, word)
s.send(msg.encode())
data = s.recv(1024).decode()
if data == 'OK':
data = s.recv(2048).decode()
print(data)
else:
print("沒有查到該單詞")
#客戶端-->查詢歷史記錄
def do_hist(s, name):
msg = 'H {}'.format(name)
s.send(msg.encode())
data = s.recv(128).decode()
if data == 'OK':
while True:
data = s.recv(1024).decode()
if data == '##':
break
print(data)
else:
print("沒有歷史記錄")
# 客戶端-->登入
def do_login(s):
name = input("User:")
passwd = getpass.getpass()
msg = 'L {} {}'.format(name, passwd)
s.send(msg.encode())
data = s.recv(1024).decode()
if data == 'OK':
return name
else:
return
# 客戶端-->註冊
def do_register(s):
while True:
name = input("User:")
passwd = getpass.getpass()
passwd1 = getpass.getpass('Again:')
if (' ' in name) or (' ' in passwd):
print("使用者名稱和密碼不允許有空格")
continue
if passwd != passwd1:
print("兩次密碼不一致")
continue
msg = 'R {} {}'.format(name, passwd)
# 傳送請求
s.send(msg.encode())
# 等待回覆
data = s.recv(1024).decode()
if data == 'OK':
return name
elif data == 'EXISTS':
return 1
else:
return 2
# 建立網路連線
def main():
if len(sys.argv) < 3:
print("argv is error")
return
HOST = sys.argv[1]
PORT = int(sys.argv[2])
s = socket()
try:
s.connect((HOST, PORT))
except Exception as e:
print(e)
return
while True:
print('''
==========Welcome=========
--1.註冊 2.登入 3.退出--
==========================
''')
try:
cmd = int(input("輸入選項>>"))
except Exception as e:
print("命令錯誤")
continue
if cmd not in [1, 2, 3]:
print("請輸入正確選項")
sys.stdin.flush() # 清除標準輸入
elif cmd == 1:
name = do_register(s)
if name:
print("註冊成功")
login(s, name)
elif name == 1:
print("使用者存在")
else:
print("註冊失敗")
elif cmd == 2:
name = do_login(s)
if name:
print("登入成功")
# 進入二級介面
login(s, name)
else:
print("使用者名稱或密碼不正確")
elif cmd == 3:
s.send(b'E')
s.close()
sys.exit("謝謝使用")
if __name__ == "__main__":
main()
3.服務端實現功能
'''
name:
date:
email:[email protected]
modules:python pymysql...
This is a dict project for AID
'''
from socket import *
import os
import sys
import time
import pymysql
import signal
# 定義需要的全域性變數
DICT_TEXT = './dict.txt' # 單詞本的位置
HOST = '0.0.0.0'
PORT = 8000
ADDR = (HOST, PORT)
# 接收請求
def do_child(c, db):
# 迴圈接收客戶端請求
while True:
data = c.recv(1024).decode()
print(c.getpeername(), ":", data)
if (not data) or data[0] == 'E':
c.close()
sys.exit("客戶端退出")
elif data[0] == 'R':
do_register(c, db, data)
elif data[0] == 'L':
do_login(c, db, data)
elif data[0] == 'Q':
do_query(c, db, data)
elif data[0] == 'H':
do_hist(c, db, data)
#服務端-->登入
def do_login(c, db, data):
print("登入操作")
L = data.split(' ')
name = L[1]
passwd = L[2]
cursor = db.cursor()
sql = "select * from user where \
name='%s' and passwd='%s'" % (name, passwd)
cursor.execute(sql)
r = cursor.fetchone()
if r == None:
c.send(b'FALL')
return
else:
print('%s登入成功' % name)
c.send(b'OK')
#服務端-->註冊
def do_register(c, db, data):
print("註冊操作")
L = data.split(' ')
name = L[1]
passwd = L[2]
cursor = db.cursor()
sql = "select * from user where name='%s'" % name
cursor.execute(sql)
r = cursor.fetchone()
if r != None:
c.send(b'EXISTS')
return
sql = "insert into user (name,passwd) values\
('%s','%s')" % (name, passwd)
try:
cursor.execute(sql)
db.commit()
c.send(b'OK')
except Exception:
db.rollback()
c.send(b'FALL')
else:
print("%s註冊成功" % name)
#服務端-->查單詞
def do_query(c, db, data):
print("查單詞操作")
L = data.split(' ')
name = L[1]
word = L[2]
cursor = db.cursor()
def insert_history():
tm = time.ctime()
sql = "insert into hist (name,word,time)\
values('%s', '%s', '%s')" % (name, word, tm)
try:
cursor.execute(sql)
db.commit()
except Exception:
db.rollback()
sql = "select * from words where word='%s'" % word
cursor.execute(sql)
try:
f = open(DICT_TEXT)
except Exception:
c.send(b'FALL')
return
for line in f:
tmp = line.split(' ')[0]
if tmp > word:
c.send(b'FALL')
f.close()
return
elif tmp == word:
c.send(b'OK')
time.sleep(0.1)
c.send(line.encode())
f.close()
insert_history()
return
c.send(b'FALL')
f.close()
#服務端-->查詢歷史記錄
def do_hist(c, db, data):
print("歷史記錄")
L = data.split(' ')
name = L[1]
cursor = db.cursor()
sql = "select * from hist where name='%s'" % name
cursor.execute(sql)
r = cursor.fetchall()
if not r:
c.send(b'FALL')
return
else:
c.send(b'OK')
for i in r:
time.sleep(0.1)
msg = "%s %s %s" % (i[1], i[2], i[3])
c.send(msg.encode())
time.sleep(0.1)
c.send(b'##')
# 流程控制
def main():
# 建立資料庫連線
db = pymysql.connect("localhost", "root", "123456", "dict")
# 建立套接字
s = socket()
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(ADDR)
s.listen(5)
# 忽略子程序訊號
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
while True:
try:
c, addr = s.accept()
print("Connect from", addr)
except KeyboardInterrupt:
s.close()
sys.exit("伺服器退出")
except Exception as e:
print(e)
continue
# 建立子程序
pid = os.fork()
if pid == 0:
s.close()
# mysql自帶鎖
do_child(c, db)
else:
c.close()
continue
if __name__ == "__main__":
main()
以上僅供參考~