基于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+'的天气:
'
    len = 0
    for i in jsons['data']['forecast']:
        if len < 2:
            if len == 0:
                str += '今日:'
            if len == 1:
                str += '明日:'
            str += i['date']
            str += '
天气:'
            str += i['type']
            str += ''
            str += i['low']
            str += ''
            str += i['high']
            str += '
'
            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的就是地名,所以手动往字典里加了很多地名,从而可以查询到大部分地方的天气了。可以下载我的字典:点击下载

原文地址:https://www.cnblogs.com/wushengyang/p/12580230.html