この記事では、Rust を使用して、都市名を入力して地域の天気を取得するコマンドライン ツールを実装します。
この記事は公式アカウント「Frontend of Puff Science」にも含まれており、記事は継続的に更新されます。
目標
ここでは Windows に実装するので、最終的な効果は次のようになります。
北京の天気を取得するためのコマンドライン入力:
weather beijing
出力:
-----正在获取天气信息, 请稍后...-----
当前温度:297.09℃
当前最低温:297.09℃
当前最高温:297.09℃
体感温度:295.7℃
湿度:6%
今日日出时间:04:55:54
今日日落时间:19:26:10
所在经度:116.3972
所在纬度:39.9075
インターフェース
ここでは無料の、アカウントを登録して、ここにアクセスして API KEY を申請します。
呼び出し方法:
https://api.openweathermap.org/data/2.5/weather?q={city name}&appid={API key}
例えば:
https://api.openweathermap.org/data/2.5/weather?q=beijing&appid=xxx
ディレクトリ構造
今回のディレクトリ構造は比較的単純で、main.rs がエントリコードを記述し、handler がメインロジックを記述します。
weather
├── Cargo.lock
├── Cargo.toml
├── README.md
├── src
│ ├── handler
│ │ └── mod.rs
│ └── main.rs
依存関係をインストールする
[package]
edition = "2021"
name = "weather"
version = "0.1.0"
[dependencies]
chrono = "0.4.19" # 时间格式化工具
colored = "2.0.0" # 控制台上色
exitfailure = "0.5.1" # 错误处理
reqwest = {version = "0.11", features = ["json"]} # 发送网络请求
serde = "1.0.114"
serde_derive = "1.0.114"
serde_json = "1.0.56"
structopt = "0.3.21" # 解析命令行参数
tokio = {version = "1", features = ["full"]}
次に依存関係をインストールし、実行しますcargo install
コーディングを開始する
上記の準備が完了したら、アプリケーションの作成を開始できます。src/main.rs
mod handler;
use handler::{print_response, Weather};
use exitfailure::ExitFailure;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
pub struct Input {
pub city: String,
}
#[tokio::main]
async fn main() -> Result<(), ExitFailure> {
// 获取命令行输入的参数,第一个参数即是 city name
let input = Input::from_args();
match Weather::get(&input.city).await {
Ok(r) => print_response(&r),
Err(e) => println!("请求出错,{:?}", &e),
};
Ok(())
}
src/handler/mod.rs
メインロジックを書く
use chrono::prelude::*;
use colored::*;
use std::time::{Duration, UNIX_EPOCH};
use exitfailure::ExitFailure;
use reqwest::Url;
use serde_derive::{Deserialize, Serialize};
/// 定义接口返回的数据结构
#[derive(Deserialize, Serialize, Debug)]
pub struct Weather {
main: Temperature,
sys: Sys,
coord: Coord,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Temperature {
temp: f64,
temp_min: f64,
temp_max: f64,
feels_like: f64,
humidity: f64,
}
#[derive(Deserialize, Serialize, Debug)]
pub struct Coord {
lon: f64,
lat: f64,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Sys {
sunrise: i32,
sunset: i32,
}
/// 定义天气接口的实现
impl Weather {
pub async fn get(city: &String) -> Result<Self, ExitFailure> {
println!("{}", "-----正在获取天气信息, 请稍后...-----".bright_green());
let url = format!("http://api.openweathermap.org/data/2.5/weather?q={}&APPID=自己去申请一下
", city);
let url = Url::parse(url.as_str())?;
let response = reqwest::get(url).await?.json::<Weather>().await?;
Ok(response)
}
}
/// 格式化时间,将时间戳转成指定格式
pub fn formate_timestamp(timestamp: i32, format: &str) -> String {
let time = UNIX_EPOCH + Duration::from_secs(timestamp as u64);
let datetime = DateTime::<Local>::from(time);
datetime.format(format).to_string()
}
/// 打印返回结果到控制台
pub fn print_response(resp: &Weather) {
println!(
" 当前温度:{}℃ \n 当前最低温:{}℃ \n 当前最高温:{}℃ \n 体感温度:{}℃ \n 湿度:{}% \n 今日日出时间:{} \n 今日日落时间:{} \n 所在经度:{} \n 所在纬度:{}",
resp.main.temp.to_string().bright_red(),
resp.main.temp_min,
resp.main.temp_max,
resp.main.feels_like,
resp.main.humidity,
formate_timestamp(resp.sys.sunrise, "%H:%M:%S"),
formate_timestamp(resp.sys.sunset, "%H:%M:%S"),
resp.coord.lon,
resp.coord.lat
);
}
/// 时间戳的单测
#[test]
fn test_timestamp_to_time() {
assert_eq!(
formate_timestamp(1643467428, "%H:%M:%S"),
"22:43:48".to_string()
);
assert_eq!(
formate_timestamp(1643467428, "%Y-%m-%d %H:%M:%S"),
"2022-01-29 22:43:48".to_string()
)
}
パッケージングと構成
最後に、コードを記述した後、それをパッケージ化する必要があります。これにより、コンソールが実行されます。
cargo build --release
パッケージ化が完了すると、target/release/weather.exe
ファイルが
次に、このファイルを環境変数で設定します。
最後に、システム内の任意の場所でコンソールを開いて、現在の天気を確認できます。
終わり~~
パブリック アカウント「Frontend of Puff Science」にご注目いただき、記事の更新を続けていただければ幸いです...