本次李骏老师的《编程思维与实践》大作业要求编写一个简易的聊天机器人,我的代码在原有基础上增加了一些情感分析、天气预报等功能,详见注释,代码仅供参考。
import random
import json
import requests # Getting HTTP Data
import tushare # Stock Market Data
import pandas
import csv
from simpleeval import simple_eval # Expression Evaluation
from datetime import datetime
from time import sleep
from termcolor import colored # Coloring Terminal
from textblob import TextBlob # English Analysis
from snownlp import SnowNLP # Chinese Analysis
from math import sin, cos, tan, sinh, cosh, tanh,\
sqrt, exp, log, log10, pow,\
asin, acos, atan, asinh, acosh, atanh
from math import pi, e
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #
# It Will take some time to initializing at the beginning of running #
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #
#########################################################
# Teruteru is a cute paper toy #
# popular in China and Japanese to pray for a sunny day #
#########################################################
#########################################################
################ Defination of Abstract Classes
#########################################################
class Chat:
usrName = "Me"
def __init__(self):
self.rsp = ""
def _thinking(self):
# Waiting for 0.6~1.2 sec beforing responding
sleep(random.uniform(0.6, 1.2))
def chat(self):
self._botTime(f"{self.rsp}\n")
def _usrTime(self):
print(f"{Chat.usrName}:", end="")
return input()
def _botTime(self, rsp):
self._thinking()
print(colored(f"Bot:{rsp}", 'blue'))
class Question(Chat):
def _respond(self, ans):
pass
def chat(self):
self._botTime(self.rsp)
self._respond(self._usrTime())
print("")
class Gossip(Chat):
def __init__(self):
self.rsp = ""
#########################################################
################ Defination of Gossip
#########################################################
class Hello(Gossip):
# Say hello to the user
def __init__(self):
self.rsp = "Hello! I'm Teru Bot. Let's have a chat!"
class Bye(Gossip):
# Say goodbye to the user
def __init__(self):
self.rsp = "Have a good time with you. Looking forward to chatting with you next time!"
class Weather(Gossip):
# Get weather forecast from the Internet
def _getWeather(self):
shJson = requests.get("http://wthrcdn.etouch.cn/weather_mini?city=%E4%B8%8A%E6%B5%B7")
shJson.encoding='utf-8'
sh = json.loads(shJson.text)
return f"Oh, I just heard about some weather information. The weather in {sh['data']['city']} will be {sh['data']['forecast'][0]['type']}, and the temperature will be {sh['data']['forecast'][0]['high']} and {sh['data']['forecast'][0]['low']}. It suggested that {sh['data']['ganmao']}"
def __init__(self):
self.rsp = self._getWeather()
class Stock(Gossip):
# Get SH and SZ stock market's index from Internet
def _drpIcs(self, num):
if num < 0:
return f"dropped by {-num}%"
else:
return f"increased by {num}%"
def _getStock(self):
idx = tushare.get_index()
return f"Hey, are you interested in stock market? Now the SH index is {idx.at[0, 'close']}, {self._drpIcs(idx.at[0, 'change'])}, and the SZ index is {idx.at[19, 'close']}, {self._drpIcs(idx.at[19, 'change'])}. It's so attractive, right?"
def __init__(self):
self.rsp = self._getStock()
class Lyrics(Gossip):
# Randomly print a lyric
def _chooseLyrics(self):
lyrics = ["东方红,太阳升,中国出了个毛泽东...",\
"Every time I'm feeling down, I can hear you say...",\
"Country road, take me home...",\
"I want something just like this, dododo dododo...",\
"时のかくれんぼ、はぐれっこはもういやなんだ...",\
"君の前前前世から仆は、君を探しはじめたよ...",\
"今天只有残留的躯壳,迎接光辉岁月...",\
"原谅我这一生不羁放纵爱自由..."]
return f"{random.choice(lyrics)} Are you hearing this song? I'm very fond of it!"
def __init__(self):
self.rsp = self._chooseLyrics()
#########################################################
################ Defination of Problem
#########################################################
class AskName(Question):
# Ask name of the user
def __init__(self):
self.rsp = "At first, what's your name?"
def _respond(self, ans):
Chat.usrName = ans # Change the user's name of displaying
self._botTime(f"All right, Nice to meet you, {Chat.usrName}.")
class ComeFrom(Question):
# Ask where the user is from
def chat(self):
self.rsp = f"Well, {Chat.usrName}, where are you from?"
super().chat()
def _respond(self, ans):
self._botTime(f"{ans}? It sounds like a fantastic place! Maybe I'll travel there one day.")
class HowsGoing(Question):
# Ask how the user's daily life is
def __init__(self):
self.rsp = "So how's it going recently?"
def _ChineseOrEnglish(self, text):
# Check if they are Chinese sentences
for ch in text:
if u'\u4e00' <= ch <= u'\u9fff':
return True
return False
def _EnglishAnalysis(self, text):
blob = TextBlob(text)
return blob.sentiment.polarity
def _ChineseAnalysis(self, text):
# Chinese analysis has some bugs
snow = SnowNLP(text)
return snow.sentiments * 2 - 1
def _respond(self, ans):
if self._ChineseOrEnglish(ans):
sentiment = self._ChineseAnalysis(ans)
else:
sentiment = self._EnglishAnalysis(ans)
# Different responds for different emotions
if sentiment >= 0.6:
self._botTime("Haha, I'm happy too!")
elif sentiment >= 0.3:
self._botTime("That sounds great!")
elif sentiment >= 0:
self._botTime("Well, all right.")
elif sentiment <= -0.6:
self._botTime("Don't be so sad, everything would be OK!")
elif sentiment <= 0.3:
self._botTime("Sorry to hear that.")
elif sentiment <= 0:
self._botTime("Well, not too bad.")
class FavColor(Question):
# Ask the user's favorite color
def __init__(self):
self.rsp = "What's your favorite color?"
def _respond(self, ans):
color = ["red", "yellow", "orange", "brown",\
"purple", "pink", "blue", "black",\
"white", "grey", "gray", "gold", "silver"]
FavClr = random.choice(color)
usrColor = ans.lower()
known = 0
for clr in color:
if usrColor.find(clr) != -1:
known = 1
if not known:
self._botTime(f"Oh, sorry I don't know what {usrColor} looks like, but my favorite color is {FavClr}.")
else:
if usrColor.find(FavClr) != -1:
self._botTime(f"Wonderful, {FavClr} is my favorite color, too!")
else:
self._botTime(f"Well, I agree that {usrColor} is beautiful, but my favorite color is {FavClr}.")
class Calc(Question):
# A simple Calculator
def __init__(self):
self.rsp = "I'm learning some arithmetic recently, so you could tell me a simple formula in Python-like format and I will tell you the answer, and press q, x, exit or quit to exit."
def chat(self):
self._botTime(self.rsp)
formular = ""
while True:
formular = self._usrTime()
if formular == "x" or formular == "q"\
or formular == "exit" or formular == "quit":
break
self._respond(formular)
print("")
def _errTime(self, err):
self._thinking()
print(colored(f"Bot:{err}", 'red'))
def _respond(self, ans):
try:
# Including some useful math functions and constants
answer = "It's a piece of cake, the answer is " + str(simple_eval(ans,
functions={"sin": lambda x: sin(x), "cos": lambda x: cos(x),\
"tan": lambda x: tan(x), "sinh": lambda x: sinh(x),\
"cosh": lambda x: cosh(x), "tanh": lambda x: tanh(x),\
"sqrt": lambda x: sqrt(x), "exp": lambda x: exp(x),\
"log": lambda x: log(x), "log10": lambda x: log10(x),\
"exp": lambda x: exp(x), "pow": lambda x, y: pow(x, y),\
"asin": lambda x: asin(x), "acos": lambda x: acos(x),\
"atan": lambda x: atan(x), "asinh": lambda x: asinh(x),\
"acosh": lambda x: acosh(x), "atanh": lambda x: atanh(x)},\
names={"e": e, "pi": pi}))\
+ ". You can ask me another!"
self._botTime(answer)
except SyntaxError:
self._errTime(f"Maybe you entered something wrong? Try again!")
except ZeroDivisionError:
self._errTime(f"Aaa-oh, it's seems like you entered something that does'nt fit math's law. Try again!")
except:
self._errTime(f"There is something I don't know in your formula? Try again!.")
#########################################################
################ Defination of TeruBot
#########################################################
class Teru:
def __init__(self):
random.seed(datetime.now())
## Gossip
self.hello = Hello()
self.bye = Bye()
self.weather = Weather()
self.stock = Stock()
self.lyrics = Lyrics()
## Problem
self.askName = AskName()
self.comeFrom = ComeFrom()
self.howsGoing = HowsGoing()
self.favColor = FavColor()
self.calc = Calc()
## Execution Table
self.queList = [self.comeFrom, self.howsGoing, self.favColor, self.calc]
self.gspList = [self.weather, self.stock, self.lyrics]
self.gspNum = len(self.gspList)
def runBot(self):
self.hello.chat()
self.askName.chat()
self._askQue()
self.bye.chat()
def _askQue(self):
for que in self.queList:
self._sayGossip()
que.chat()
def _sayGossip(self):
# 68% Possibility to run
if not(random.random() < 0.68 and self.gspNum):
return
choiceGsp = random.randint(0, self.gspNum - 1)
self.gspList[choiceGsp].chat()
# Fisher–Yates Shuffle Algorithm
tmpGsp = self.gspList[self.gspNum - 1]
self.gspList[self.gspNum - 1] = self.gspList[choiceGsp]
self.gspList[choiceGsp] = tmpGsp
self.gspNum -= 1
#########################################################
################ Runing Entrance
#########################################################
teruBot = Teru()
teruBot.runBot()