# 基于词性分析和魅族天气的天气查询机器人
本文将基于 jieba-php
(opens new window) 中文分词库以及 魅族天气 API (opens new window) 开发一个天气查询机器人。
# 结果演示
尾部的随机表情并非本教程的一部分。
# 逻辑编写
jieba-php (opens new window) 是目前比较好用的中文分词库,虽然最近的维护并不活跃,但已足够我们的需求:
composer require fukuball/jieba-php:dev-master
1
以下代码使用了本文作者自行编写的天气查询库,需要进行引入:
composer require sunxyw/weather
1
您也可以将以下代码自行改写为直接调用魅族天气 API,详情请参阅魅族天气 API 文档 (opens new window)。
<?php
namespace Bot\Module\SmartChat;
use Fukuball\Jieba\Jieba;
use Fukuball\Jieba\Posseg;
use Sunxyw\Weather\Weather;
use ZM\Annotation\CQ\CQCommand;
use ZM\Console\Console;
class WeatherReport
{
/**
* 加载字典
*
* @OnStart(worker_id=-1)
*
* @return void
*/
public function initDictionary(): void
{
// 分词以及词性分析需要载入字典到内存
ini_set('memory_limit', '600M');
Jieba::init(['dict' => 'small']);
Posseg::init();
}
/**
* 查询天气
*
* @CQCommand(keyword="天气")
*
* @return string
*/
public function cmdQueryWeather(): string
{
// 分词并进行词性分析
$seg_list = Posseg::cut(ctx()->getMessage());
$tags = array_column($seg_list, 'tag');
// 找出词性为 ns(地名)的单词
$location_index = array_search('ns', $tags, true);
$location = $seg_list[$location_index]['word'];
// 此处引入了本文作者自己写的天气库
$w = new Weather();
try {
$report = $w->getWeather($location);
} catch (\InvalidArgumentException) {
return '城市输入错误';
} catch (\JsonException $e) {
Console::warning("天气查询失败:{$e->getMessage()}");
return '天气查询失败';
}
$template = <<<EOF
%s天气:%s
温度:%s℃
湿度:%s%%
风向:%s %s
空气质量:%s
------------------------------
未来三天天气:
%s:%s,日间%s℃,夜间%s℃,吹%s %s
%s:%s,日间%s℃,夜间%s℃,吹%s %s
%s:%s,日间%s℃,夜间%s℃,吹%s %s
EOF;
$args = [
$report->getCity(),
$report->getRealtime()['weather'],
$report->getRealtime()['temperature'],
$report->getRealtime()['humidity'],
$report->getRealtime()['wind_direction'],
$report->getRealtime()['wind_speed'],
$report->getRealtime()['air_quality'],
];
foreach (array_slice($report->getForecastDaily(), 0, 3) as $forecast) {
$args[] = $forecast['date'];
$args[] = $forecast['weather'];
$args[] = $forecast['temperature']['day'];
$args[] = $forecast['temperature']['night'];
$args[] = $forecast['wind_direction'];
$args[] = $forecast['wind_speed'];
}
return vsprintf($template, ...$args);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86