首页 >> 大全

从零开始用Python做一个女朋友 • 第一弹

2023-11-17 大全 33 作者:考证青年

从零开始用做一个女朋友 • 第一弹 因为一只蝙蝠所引起的一系列连锁反应,导致一直宅在家中的自己突然有了重拾的勇气,一直以来想要做个智能对话机器人,于是说干就干,从最简单的关键词匹配做起,在目前进度中,通过调用公共接口实现了天气查询和实时新闻查询两个功能,后续功能将逐渐完善。由于本人学识不深,很多细节的处理上可能不尽完善,欢迎各位大佬指点~

由于目标是比较智能的机器人,所以借用了动漫刀剑的梗虚拟人物形象叫Alice 【宅属性暴露无遗】

总体思路还是模块化的思想,通过循环接收用户输入,然后通过自定义的()函数进行关键词匹配,将匹配结果通过数组返回,并在主过程内遍历数组内的事件标签,如果天气查询标签或新闻查询标签在内,则将用户输入传递给相应的自定义模块函数进行处理。话不多说,先呈上main.py模块代码:

python"># -*- coding:utf-8 -*-
import weather  #自定义天气查询处理模块
import news     #自定义新闻查询处理模块def __analyse(raw_str):analyse_result = []weather_wors = ['天气', 'weather']news_words = ['新闻', 'news', "头条"]if any(word in raw_str for word in weather_wors):analyse_result.append('weather')    #为返回的结果数组添加'weather'标签if any(word in raw_str for word in news_words):analyse_result.append('news')       #为返回的结果数组添加'news'标签return analyse_resultif __name__ == '__main__':while (True):raw_str = input()analyse_result = __analyse(raw_str)if 'weather' in analyse_result:weather.handle(raw_str)     #调用自定义天气查询处理模块的处理函数if 'news' in analyse_result:news.handle(raw_str)        #调用自定义新闻查询处理模块的处理函数else:print('Alice没能听懂主人说的是什么哇……')

下面以.py为例解释天气查询内部的处理过程(news.py模块同理):

自定义模块的()函数在接收到用户输入后,也是首先调用本模块内的()函数进行关键词匹配,与main模块内不同的是,由于返回的结果除去标签还需要一部分属性值,譬如说天气查询的地点、时间等,所以定义了Tag便签对象,用来作为返回的标签数组的元素。

class Tag:name = ''       #标签名props = {}      #属性值def __init__(self, name, props):self.name = nameself.props = props

为了更加方便地修改定制,我增加了读取目录下配置文件.ini获取默认值及查询接口API的功能,相关代码如下:

import configparser     #可以通过 pip install 进行安装
import os__config = configparser.ConfigParser()
__config.read(os.getcwd() + "/config.ini", encoding='utf-8')__weather_api_url = __config.get("weather", "api")      #天气查询API链接
__weather_api_key = __config.get("weather", "key")      #天气查询API的个人密钥
__weather_default_city = __config.get("weather", "default_city")    #在未指定查询城市时默认的查询城市
__temp_threshold = __config.get("weather", "temp_threshold")        #温差提醒阈值
__wind_threshold = __config.get("weather", "wind_threshold")        #风力提醒阈值

.ini文件的内容如下:

[weather]
; 天气查询API
api=http://apis.juhe.cn/simpleWeather/query
; 天气查询默认城市
default_city=长沙
; 天气查询API密钥
key=***************
; 温差提醒阈值
temp_threshold=15
; 风力提醒阈值
wind_threshold=6

天气查询及新闻查询API使用来源于 [聚合数据] ,个人作为开发者注册认证之后每天可以免费调用100次,个人使用完全足够了,在右上角“个人中心” -> “数据中心” -> “我的接口”内可以搜索和申请接口,接口申请成功后会自动分配一个Key,之后每次调用时需要携带这个Key进行访问。

点击图二右侧“测试”按钮可以进入测试页面,网页将模拟真实调用的情形对请求参数以及返回数据进行展示,为了辅助接下来的代码展示,先展示一下某次查询链接以及返回的json数据:

http://apis.juhe.cn/simpleWeather/query?city=%E9%95%BF%E6%B2%99&key=************
// 注意此处的city参数必须为 utf8 urlencode 形式

{"reason":"查询成功","result":{"city":"长沙","realtime":{"temperature":"14","humidity":"73","info":"阴","wid":"02","direct":"西南风","power":"2级","aqi":"55"},"future":[{"date":"2020-02-22","temperature":"11\/18℃","weather":"多云","wid":{"day":"01","night":"01"},"direct":"北风转南风"},{"date":"2020-02-23","temperature":"11\/22℃","weather":"晴转多云","wid":{"day":"00","night":"01"},"direct":"南风"},{"date":"2020-02-24","temperature":"15\/26℃","weather":"多云","wid":{"day":"01","night":"01"},"direct":"南风"},{"date":"2020-02-25","temperature":"17\/25℃","weather":"阵雨","wid":{"day":"03","night":"03"},"direct":"南风"},{"date":"2020-02-26","temperature":"12\/23℃","weather":"阵雨","wid":{"day":"03","night":"03"},"direct":"北风"}]},"error_code":0
}

然后接下来就是.py模块中文本分析函数()的实现了,为了方便阅读,此处将支持从城市关键词数组只展示一部分,所有支持查询的城市大家也可以在 [聚合数据] 上进行查询,该网站也提供了查询支持的城市的API:

def __analyse(raw_str):analyse_result = []weather_query_words = ['?', '怎么样', '如何']weather_talk_words = ['不错', '喜欢', '不喜欢']city_words = ['北京', '海淀', '朝阳', '顺义', '怀柔', '通州', '昌平', '延庆', '丰台', '石景山', '大兴', '房山', '密云', '门头沟', '平谷', '上海']       #支持查询的城市关键词if any(word in raw_str for word in weather_query_words):query_props = {'time': 'TODAY', 'city': __weather_default_city}     #如果未指定查询时间和城市则默认查询今天以及config.ini配置文件中城市的天气today_words = ['今天', 'today']         #查询时间为“今天”的关键词tomorrow_words = ['明天', 'tomorrow']   #查询时间为“明天”的关键词twodays_words = ['今天和明天', '今明']  #查询时间为“今明两天”的关键词if any(word in raw_str for word in today_words):query_props['time'] = 'TODAY'if any(word in raw_str for word in tomorrow_words):query_props['time'] = 'TOMORROW'if any(word in raw_str for word in twodays_words):query_props['time'] = 'TWODAYS'for city in city_words:if city in raw_str:query_props['city'] = citybreakanalyse_result.append(Tag('weather-query', query_props))if any(word in raw_str for word in weather_talk_words):analyse_result.append(Tag('weather-talk', None))return analyse_result

在()调用分析之后,接下来就是()函数进行处理的部分了:

def handle(raw_str):analyse_result = __analyse(raw_str)     #对主过程传入的raw_str进行关键词分析for tag in analyse_result:if tag.name == 'weather-talk':print('今天的天气真的很不错哦')if tag.name == 'weather-query':weather_complete_api = __weather_api_url + "?city=" + quote(tag.props["city"]) + "&key=" + __weather_api_key        #调用quote函数将城市名转为 utf8 urlencode 形式并拼凑URLweather_response = json.loads(requests.get(weather_complete_api).content)       #调用天气查询API并获取返回JSON格式的结果error_code = weather_response['error_code']#处理异常状态if (error_code == 207301 or error_code == 207302):print("Alice不知道这座城市是哪里的呢……要不主人再换一个试试?")elif (error_code == 207303):print("哔——电波在传输过程中好像出了点问题哎……")elif (error_code == 0):        #错误码为0代表查询成功print("嘀哩哩~数据接收完成,下面为主人播报天气——")city = weather_response["result"]["city"]       #返回的JSON内反馈的查询结果城市info_today = weather_response["result"]["future"][0]["weather"]         #今日的天气状况temperature_today = weather_response["result"]["future"][0]["temperature"]      #今天的最低气温和最高气温temperature_today_min = temperature_today[:temperature_today.find('/')]     #处理temperature_today获得今日最低气温temperature_today_max = temperature_today[temperature_today.find('/') + 1:temperature_today.find('℃')]      #处理temperature_today获得今日高气温info_tomorrow = weather_response["result"]["future"][1]["weather"]      #明日天气状况temperature_tomorrow = weather_response["result"]["future"][1]["temperature"]       #明日的最低气温和最高气温temperature_tomorrow_min = temperature_tomorrow[:temperature_tomorrow.find('/')]        #处理temperature_today获得明日最低气温temperature_tomorrow_max = temperature_tomorrow[temperature_tomorrow.find('/') + 1:temperature_tomorrow.find('℃')]       #处理temperature_today获得明日高气温wind_direction_today = weather_response["result"]["future"][0]["direct"]        #今日风向wind_direction_tomorrow = weather_response["result"]["future"][1]["direct"]     #明日风向wind_power_now = weather_response["result"]["realtime"]["power"]                #当前时间风力大小#对标签内各属性值进行匹配处理if tag.props['time'] == 'TODAY':response_text = "今天[" + city + "]天气" + info_today + ",气温 " + temperature_today + ",今天风向为" + wind_direction_today + ",当前风力" + wind_power_now + "。"if (int(temperature_today_max) - int(temperature_today_min) >= int(__temp_threshold)):response_text = response_text + "\n今天昼夜温差很大的说,主人要多加注意穿衣保暖哦~"if (int(wind_power_now[:-1]) >= int(__wind_threshold)):response_text = response_text + "\n另外,现在的风也有点大呢,主人一定当心不要被风吹跑啦,嘻嘻~"print(response_text)if tag.props['time'] == 'TOMORROW':response_text = "明天[" + city + "]天气" + info_tomorrow + ",气温 " + temperature_tomorrow + ",风向为" + wind_direction_tomorrow + "。"if (int(temperature_tomorrow_max) - int(temperature_tomorrow_min) >= int(__temp_threshold)):response_text = response_text + "\n明天昼夜温差很大的说,主人要多加注意穿衣保暖哦~"print(response_text)if tag.props['time'] == 'TWODAYS':response_text = "今天[" + city + "]天气" + info_today + ",气温 " + temperature_today + ",今天风向为" + wind_direction_today + ",当前风力" + wind_power_now + ";\n明天天气" + info_tomorrow + ",气温 " + temperature_tomorrow + ",风向为" + wind_direction_tomorrow + "。"if (int(temperature_today_max) - int(temperature_today_min) >= int(__temp_threshold) or int(temperature_tomorrow_max) - int(temperature_tomorrow_min) >= int(__temp_threshold)):response_text = response_text + "\n今明两天昼夜温差很大的说,主人要多加注意穿衣保暖哦~"if (int(wind_power_now[:-1]) >= int(__wind_threshold)):response_text = response_text + "\n另外,现在的风也有点大呢,主人一定当心不要被风吹跑啦,嘻嘻~"print(response_text)else:print("发生了Alice也不清楚的错误呢(๑Ő௰Ő๑)……要不主人帮忙看一下\n错误代码:[Weather-API:" + error_code + "]")     #对于API的系统性错误直接抛出错误代码处理

由于使用了文字转码以及JSON处理等操作,.py需要导入的全部包如下:

from urllib.parse import quote
import configparser
import requests
import json
import os

最后看一下实战效果吧:

目前实现的功能模块细节就如上所述啦,后序会添加更多的非功能性的模块,譬如情感处理以及好感度等模块,欢迎有新意的脑洞,[源码]

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了