2022-03-19 21:25:10 +08:00
|
|
|
|
# 基于词性分析和魅族天气的天气查询机器人
|
|
|
|
|
|
|
|
|
|
|
|
本文将基于 [`jieba-php`](https://github.com/fukuball/jieba-php) 中文分词库以及 [魅族天气 API](https://github.com/shichunlei/-Api/blob/master/MeizuWeather.md) 开发一个天气查询机器人。
|
|
|
|
|
|
|
|
|
|
|
|
## 结果演示
|
2022-03-22 00:51:03 +08:00
|
|
|
|
|
2022-03-19 21:25:10 +08:00
|
|
|
|

|
|
|
|
|
|
尾部的随机表情并非本教程的一部分。
|
|
|
|
|
|
|
|
|
|
|
|
## 逻辑编写
|
|
|
|
|
|
|
2022-03-22 00:51:03 +08:00
|
|
|
|
[jieba-php](https://github.com/fukuball/jieba-php) 是目前比较好用的中文分词库,虽然最近的维护并不活跃,但已足够我们的需求:
|
|
|
|
|
|
|
2022-03-19 21:25:10 +08:00
|
|
|
|
```shell
|
|
|
|
|
|
composer require fukuball/jieba-php:dev-master
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
以下代码使用了本文作者自行编写的天气查询库,需要进行引入:
|
2022-03-22 00:51:03 +08:00
|
|
|
|
|
2022-03-19 21:25:10 +08:00
|
|
|
|
```shell
|
|
|
|
|
|
composer require sunxyw/weather
|
|
|
|
|
|
```
|
2022-03-22 00:51:03 +08:00
|
|
|
|
|
2022-03-19 21:25:10 +08:00
|
|
|
|
您也可以将以下代码自行改写为直接调用魅族天气 API,详情请参阅[魅族天气 API 文档](https://github.com/shichunlei/-Api/blob/master/MeizuWeather.md)。
|
|
|
|
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
|
<?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
|
|
|
|
|
|
{
|
|
|
|
|
|
/**
|
2022-03-19 21:35:48 +08:00
|
|
|
|
* 加载字典
|
2022-03-19 21:25:10 +08:00
|
|
|
|
*
|
2022-03-19 21:35:48 +08:00
|
|
|
|
* @OnStart(worker_id=-1)
|
2022-03-19 21:25:10 +08:00
|
|
|
|
*
|
2022-03-19 21:35:48 +08:00
|
|
|
|
* @return void
|
2022-03-19 21:25:10 +08:00
|
|
|
|
*/
|
2022-03-19 21:35:48 +08:00
|
|
|
|
public function initDictionary(): void
|
2022-03-19 21:25:10 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 分词以及词性分析需要载入字典到内存
|
|
|
|
|
|
ini_set('memory_limit', '600M');
|
|
|
|
|
|
Jieba::init(['dict' => 'small']);
|
|
|
|
|
|
Posseg::init();
|
2022-03-19 21:35:48 +08:00
|
|
|
|
}
|
2022-03-19 21:25:10 +08:00
|
|
|
|
|
2022-03-19 21:35:48 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 查询天气
|
|
|
|
|
|
*
|
|
|
|
|
|
* @CQCommand(keyword="天气")
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function cmdQueryWeather(): string
|
|
|
|
|
|
{
|
2022-03-19 21:25:10 +08:00
|
|
|
|
// 分词并进行词性分析
|
|
|
|
|
|
$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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|