天天看點

基于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的就是地名,是以手動往字典裡加了很多地名,進而可以查詢到大部分地方的天氣了。可以下載下傳我的字典:點選下載下傳