基于NoneBot的天气查询插件
搞了一会才弄出了个天气的插件,主要是根据官方文档的完善,从而能实现查询天气的功能。
主函数:(__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的就是地名,所以手动往字典里加了很多地名,从而可以查询到大部分地方的天气了。可以下载我的字典:点击下载