搞了一会才弄出了个天气的插件,主要是根据官方文档的完善,从而能实现查询天气的功能。
主函数:(__init__.py)
from nonebot import on_command, CommandSession from nonebot import on_natural_language, NLPSession, IntentCommand from jieba import posseg import requests import time import urllib from lxml import etree from .data_source import get_weather_of_city @on_command('weather', aliases=('的天气', '天气预报', '查天气')) async def weather(session: CommandSession): city = session.get('city', prompt='你想查询哪个城市的天气呢?') weather_report = await get_weather_of_city(city) await session.send(weather_report) @weather.args_parser async def _(session: CommandSession): stripped_arg = session.current_arg_text.strip()
# current_arg_text.strip()是用来去掉字符串的首位空格 if session.is_first_run: if stripped_arg: session.state['city'] = stripped_arg return
if not stripped_arg: session.pause('要查询的城市名称不能为空呢,请重新输入') session.state[session.current_key] = stripped_arg # on_natural_language 装饰器将函数声明为一个自然语言处理器 # keywords 表示需要响应的关键词,类型为任意可迭代对象,元素类型为 str # 如果不传入 keywords,则响应所有没有被当作命令处理的消息
@on_natural_language(keywords={'的天气'},only_to_me=False) async def _(session: NLPSession): # 去掉消息首尾的空白符
stripped_msg = session.msg_text.strip() print(stripped_msg) # 对消息进行分词和词性标注
words = posseg.lcut(stripped_msg) city = None # 遍历 posseg.lcut 返回的列表
for word in words: # 每个元素是一个 pair 对象,包含 word 和 flag 两个属性,分别表示词和词性
if word.flag == 'ns': # ns 词性表示地名
print(word.flag) city = word.word break
# 返回意图命令,前两个参数必填,分别表示置信度和意图命令名
return IntentCommand(90.0, 'weather', current_arg=city)
具体实现的接口方面的:(data_source.py文件的)
from urllib.request import urlopen import urllib.request import requests import sys import ssl import importlib importlib.reload(sys) import json async def get_weather_of_city(city: str) -> str: # 这里简单返回一个字符串
# 实际应用中,这里应该调用返回真实数据的天气 API,并拼接成天气预报内容
host = 'http://wthrcdn.etouch.cn/weather_mini?city=' url = host + urllib.parse.quote(city) r = requests.get(url) jsons = json.loads(r.text) str = city+'的天气:\n' len = 0 for i in jsons['data']['forecast']: if len < 2: if len == 0: str += '今日:'
if len == 1: str += '明日:' str += i['date'] str += '\n天气:' str += i['type'] str += '\n最' str += i['low'] str += '\n最' str += i['high'] str += '\n' len += 1
return str
总结:
算是折腾了挺久的吧,总结下遇到的问题。
1.一开始用的阿里云的免费接口,返回的是json格式,由于一般我们需要查询的城市格式是utf-8的字符串,但是python中默认的是ascii的格式来运行,所以还得先utf-8转Unicode,但是转换的时候经常会报各种各样的错误。后面换了别的接口,直接用requests库。在python3中,urllib2库已经没有了,用来代替的是urrlib.request库
2.由于是采用的浏览器get方法,所以在查询的时候城市需要转换成urlcode,才能拼接到url后面,用的是urllib.parse.quote()这个函数,可以直接转换。
3.jieba分词器的自带字典里面很多地名没有标注,其由三部分组成 (词语 曝光度 代表号),一般代表号=ns的就是地名,所以手动往字典里加了很多地名,从而可以查询到大部分地方的天气了。可以下载我的字典:点击下载