使用Openweathermap API在Node.js中创建一个天气应用程序
天气预报对于我们的日常生活是非常必要的。它可以帮助我们根据预期做好准备和制定计划。许多气象站被放置在世界各地,以获取实时的天气元素数据。
这些数据包括六个元素,如降水、风、大气压力、云量和温度。有了这些,你可以分析趋势,知道明天的数据预测或预测天气。
这些大块的数据大多是在基站使用强大而复杂的系统进行处理。然后他们通过API分享这些数据,(无论是长期分析的数据还是实时数据)。这样做的公司包括OpenWeatherMap和Dark Sky。
在本教程中,你将学习如何使用OpenWeatherMap API建立一个漂亮的天气应用程序。
主要收获
在本教程结束时,你将学会。
- 什么是OpenWeatherMap API。
- 如何使用OpenWeatherMap API。
- 如何使用HTML、CSS和JavaScript建立一个漂亮的天气网站。
- 如何将API集成到系统中。
- 如何运行网络应用程序。
先决条件
跟随本教程所需的一些基础知识包括。
- 网络开发过程中的一些基本知识。
- Node.js的基础知识。
- 在电脑上安装一个IDE/文本编辑器。
- 一个良好和稳定的网络连接。
如果你具备以上所有条件,让我们进入一个工作项目的步骤。
获取API密钥
访问openweathermap.org/,并创建一个新的帐户,如果你已经有一个帐户,请登录。
OpenWeatherMap。提供免费和付费服务。这完全取决于所要求的数据的类型和大小。此外,它也取决于每次请求的数量。

点击你在导航栏右上方的账户名称链接。在下拉菜单中,选择 "我的API密钥"。你可以用新的名字生成一个,或使用所提供的默认的一个。
为安全起见,请确保它不被任何人看到。另外,不要在你的应用程序中直接保存它。
如果出现任何无效的 "无效的API密钥"错误,你可以创建一个新的密钥并保存起来使用。一个以前从未使用过的。
设置项目
创建一个新的目录,这将是你的根目录,并将其命名为Weather ,在其中,你将通过使用下面的命令初始化Node.js项目。
npm init -y
该命令接受终端对话中的所有默认选项。它在根目录下创建一个新的配置文件,名为package.json 。
接下来,创建一个名为views 的文件夹,并在其中创建一个名为index.ejs 的文件。这个文件将允许我们使用ejs 视图引擎查看结果。
在根目录下创建另一个名为public 的文件夹,并在其中创建一个名为css 的文件夹。在根目录下创建分别名为.env 和server.js 的文件。项目的结构将如下图所示。
文件夹结构
.Weather
├── node_modules (Folder)
├── public (Folder)
│ ├── css (Folder)
│ └── style.css (File)
├── views (Folder)
│ └── index.ejs (File)
├── .env (File)
├── package.json (File)
└── server.js (File)
现在你将修改你的文件,如下。
安装依赖项
以下是你在项目中需要的依赖项。
- Express:这将帮助我们创建服务器并提供你的API。
- dotenv:这将帮助我们访问
.env文件中的隐藏键。 - body-parser:这是一个Node.js主体解析中间件。它将允许我们在你的处理程序之前在中间件中解析传入的请求体。这些都是在
req.body属性下可用的。 - request:这将有助于进行http调用。
- ejs:这将有助于将你的模板转换为可在浏览器中查看的HTML静态页面。
你将通过在终端运行以下命令来安装它们。
npm i express dotenv body-parser request ejs
检查应用程序的配置
让我们调整一下package.json 文件中的应用程序配置。
打开该文件并在其中添加一个启动脚本,如下所示。
...
"scripts": {
"start": "node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
...
你的完整的package.json ,看起来应该是这样的。
{
"name": "Weather",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.17.2",
"dotenv": "^10.0.0",
"express": "^4.15.3",
"request": "^2.81.0"
}
}
应用程序入口点
前往server.js 文件,这是你的应用程序的主要入口点。
你将需要在你的代码中做以下工作。
- 导入应用程序的依赖性
这些是你在你的应用程序中安装的依赖项。为了使用它们,你可以使用require 关键字来导入它们,如下图所示。
// Require application dependencies
// These are express, body-parser, and request
const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
const app = express();
// Configure dotenv package
require("dotenv").config();
- 设置你的API KEY、Express应用程序和body-parser配置,以及你的JavaScript模板视图引擎。
// Set up your OpenWeatherMap API_KEY
const apiKey = `${process.env.API_KEY}`;
// Setup your express app and body-parser configurations
// Setup your javascript template view engine
// we will serve your static pages from the public directory, it will act as your root directory
app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: true }));
app.set("view engine", "ejs");
- 接下来,你将设置启动时的默认显示。这基本上是用户在向
/路径运行获取请求时将看到的页面。
// Setup your default display on launch
app.get("/", function (req, res) {
// It will not fetch and display any data in the index page
res.render("index", { weather: null, error: null });
});
- 接下来,设置post request的显示。这是当你用你想要的数据向API发出帖子请求时显示的页面。你的获取将在页面加载时发生在
/端点上。
在这里,你将使用帖子请求中传递的城市和你的.env 文件中的API_KEY来从API获取数据。
// On a post request, the app shall data from OpenWeatherMap using the given arguments
app.post('/', function(req, res) {
// Get city name passed in the form
let city = req.body.city;
// Use that city name to fetch data
// Use the API_KEY in the '.env' file
let url = `http://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${apiKey}`;
- 接下来,我们将使用URL中传递的凭证从OpenWeatherMap API请求数据。在正文部分找到的数据将被存储在本地变量中,然后在网页上呈现。
如果出现错误,它将显示一个错误信息,如下图所示。
// Request for data using the URL
request(url, function(err, response, body) {
// On return, check the json data fetched
if (err) {
res.render('index', { weather: null, error: 'Error, please try again' });
} else {
let weather = JSON.parse(body);
- 接下来,你将检查你的天气数据是否返回未定义。这将表明有错误。如果不是,你将继续存储内容。
// you shall output it in the console just to make sure that the data being displayed is what you want
console.log(weather);
if (weather.main == undefined) {
res.render('index', { weather: null, error: 'Error, please try again' });
} else {
// we shall use the data got to set up your output
let place = `${weather.name}, ${weather.sys.country}`,
/* you shall calculate the current timezone using the data fetched*/
weatherTimezone = `${new Date(
weather.dt * 1000 - weather.timezone * 1000
)}`;
let weatherTemp = `${weather.main.temp}`,
weatherPressure = `${weather.main.pressure}`,
/* you will fetch the weather icon and its size using the icon data*/
weatherIcon = `http://openweathermap.org/img/wn/${weather.weather[0].icon}@2x.png`,
weatherDescription = `${weather.weather[0].description}`,
humidity = `${weather.main.humidity}`,
clouds = `${weather.clouds.all}`,
visibility = `${weather.visibility}`,
main = `${weather.weather[0].main}`,
weatherFahrenheit;
weatherFahrenheit = (weatherTemp * 9) / 5 + 32;
// you shall also round off the value of the degrees fahrenheit calculated into two decimal places
function roundToTwo(num) {
return +(Math.round(num + "e+2") + "e-2");
}
weatherFahrenheit = roundToTwo(weatherFahrenheit);
- 接下来,存储的值现在将被渲染到网页上,生成一个静态网页,显示给用户。
// you shall now render the data to your page (index.ejs) before displaying it out
res.render("index", {
weather: weather,
place: place,
temp: weatherTemp,
pressure: weatherPressure,
icon: weatherIcon,
description: weatherDescription,
timezone: weatherTimezone,
humidity: humidity,
fahrenheit: weatherFahrenheit,
clouds: clouds,
visibility: visibility,
main: main,
error: null,
});
}
}
}
});
});
注意:你可以根据需要获取和显示尽可能多的数据。这是在收到的JSON中。
- 设置你的服务器端口配置并启动服务器。
这里你将设置你的服务器监听端口。你还将启动服务器,并添加一个运行时显示的信息。你将为你的项目利用端口5000 ,可以在http://localhost:5000 。
// you will set up your port configurations. You will also start the server and add a message to display when running.
app.listen(5000, function () {
console.log("Weather app listening on port 5000!");
});
你可以直接复制代码并将其粘贴到你的文件中。
设置你的视图
现在让我们在应用程序中设置你的动态网页。记住,你正在使用EJS作为你的模板引擎。在views 文件夹中找到的index.ejs 文件中,你将创建一个网页模板,在显示过程中,一旦取到值,将被转换为静态网页。
注意:当这个渲染静态网页时,它们将从
public文件夹中被提供,它将作为根目录。这是因为在server.js文件中的这行代码,app.use(express.static('public'));。因此,它将从'public'文件夹中获得其资产。这将包括'css'甚至是图像文件。
这就是你将在index.ejs 文件中做的事情。
- 在你的
index.ejs中创建一个新的bootstrap boilerplate。链接将在'css'文件夹内找到的css文件。在其中,你还将把网站的标题改为Weather,并从一个URL中添加一个favicon,如下面的代码所示。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Weather</title>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<!-- Bootstrap CSS -->
<!-- Use some bootstrap CSS and google fonts to quicken the process -->
<!-- you shall also add a favicon -->
<link
rel="shortcut icon"
href="https://img.icons8.com/office/16/000000/sunset--v2.png"
type="image/x-icon"
/>
<link rel="stylesheet" type="text/css" href="/css/style.css" />
<link
href="https://fonts.googleapis.com/css?family=Open+Sans:300"
rel="stylesheet"
type="text/css"
/>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
crossorigin="anonymous"
/>
</head>
<body>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script
src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"
></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"
></script>
</body>
</html>
- 在body标签内,就在bootstrap脚本的上方,你将添加你的内容。你还应使用数据属性来访问从API渲染到它的数据。如果没有数据,它将显示错误。
<!-- Main container -->
<div class="container">
<!-- This shall hold the input fields and the output data -->
<fieldset>
<!-- This form shall be used to fetch your city name -->
<form action="/" method="post">
<input name="city" type="text" class="ghost-input" placeholder="Enter a City" required>
<input type="submit" class="ghost-button" value="Get Weather">
</form>
<!-- Upon fetching of data you will display it -->
<%if( weather !== null){ %>
<div class="grid">
<p>
<%= place %>
</p>
<p class="text-muted small">
<%= timezone %>
</p>
</div>
<!-- You can find other data fetched by the app on the console in JSON form and display it as you please -->
<div class="card-deck">
<div class="card card-accent-dark mb-3" style="max-width: 18rem;">
<div class="card-header">Summary</div>
<div class="card-body text-dark">Bootstrap CSS
<img src="<%= icon %>" alt="Weather-Icon">
<h5 class="card-title">Temperature</h5>
<p class="card-text">
In Degrees:
<%= temp %>°C/
<%= fahrenheit %>°F
</p>
<h5 class="card-title">Main</h5>
<p class="card-text">
<%= main %>
</p>
</div>
</div>
<div class="card-deck">
<div class="card card-acTomorrowcent-dark mb-3" style="max-width: 18rem;">
<div class="card-header">Description</div>
<div class="card-body text-dark">
<h5 class="card-title">Overall Description: </h5>
<p class="card-text">
<%= description %>
</p>
<h5 class="card-title">Cloud coverage: </h5>
<p class="card-text">
<%= clouds %>%
</p>
<h5 class="card-title">Visibility: </h5>
<p class="card-text">
<%= visibility %> meters
</p>
</div>
</div>
<div class="card-deck">
<div class="card card-accent-dark mb-3" style="max-width: 18rem;">
<div class="card-header">Other info</div>
<div class="card-body text-dark">
<h5 class="card-title">Humidity: </h5>
<p class="card-text">
<%= humidity %> g.m-3
</p>
</div>
<div class="card-body text-dark">
<h5 class="card-title">Pressure: </h5>
<p class="card-text">
<%= pressure %> N·m−2
</p>
</div>
</div>
</div>
<% } %>
<% if(error !== null){ %>
<p>
<%= error %>
</p>
<% } %>
</fieldset>
</div>
注意:脚本总是放在你的页面上的主要内容之后。这将允许页面内容在执行JavaScript文件之前完全加载,从而防止错误。这是很好的编码实践。
塑造你的页面
在代码执行过程中,你应使用你的'style.css'文件对生成并存储在公共文件夹中的静态网页进行造型。
这将是你的CSS格式。
body {
width: auto;
margin: 0 auto;
font-family: "Open Sans", sans-serif;
}
/* This will format the whole fieldset content*/
.container {
width: 80%;
margin: 0 auto;
}
/* This will format the whole fieldset content*/
fieldset {
display: block;
-webkit-margin-start: 0px;
-webkit-margin-end: 0px;
-webkit-padding-before: 0em;
-webkit-padding-start: 0em;
-webkit-padding-end: 0em;
-webkit-padding-after: 0em;
border: 0px;
border-image-source: initial;
border-image-slice: initial;
border-image-width: initial;
border-image-outset: initial;
border-image-repeat: initial;
min-width: -webkit-min-content;
padding: 30px;
}
/* Format the input section */
/* Format the input, paragraph, hover effect, focus and button */
.ghost-input,
p {
display: block;
font-weight: 300;
width: 100%;
font-size: 25px;
border: 0px;
outline: none;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
color: #4b545f;
background: #fff;
font-family: Open Sans, Verdana;
padding: 10px 15px;
margin: 30px 0px;
-webkit-transition: all 0.1s ease-in-out;
-moz-transition: all 0.1s ease-in-out;
-ms-transition: all 0.1s ease-in-out;
-o-transition: all 0.1s ease-in-out;
transition: all 0.1s ease-in-out;
}
.ghost-input:focus {
border-bottom: 1px solid #ddd;
}
.ghost-button {
background-color: transparent;
border: 2px solid #ddd;
padding: 10px 30px;
width: 100%;
min-width: 350px;
-webkit-transition: all 0.1s ease-in-out;
-moz-transition: all 0.1s ease-in-out;
-ms-transition: all 0.1s ease-in-out;
-o-transition: all 0.1s ease-in-out;
transition: all 0.1s ease-in-out;
}
.ghost-button:hover {
border: 2px solid #515151;
}
p {
color: #e64a19;
}
应用环境变量
你现在将输入你的应用环境常量。在你的.env 文件内,你将放置你的OpenWeatherMap API KEY。
只需在文件中添加以下内容,然后在其后面复制粘贴获得的密钥。
API_KEY=
保存该文件。
运行和访问该应用程序
要运行该应用程序,你将利用先前在'package.json'文件中添加的'start'脚本。
这可以通过在内置终端中运行以下代码来完成。
npm run start
你也可以用以下方式启动该应用程序。
node server.js
在浏览器中访问该应用程序:localhost:5000 。输入您选择的城市名称,并点击 "获取天气 "按钮。
它将获取天气数据并在网络浏览器和控制台中返回结果。
你可以在终端上使用Ctrl + C 关闭该应用程序。
额外的项目API
- OpenWeatherMap有更多的API调用,用于其他类型的预测,是免费的。这可以在这个链接中找到:https://openweathermap.org/api。
一些显示在下面。

你可以尝试获取数据并在控制台或浏览器中显示它。
- 尝试获取并使用地理定位,根据用户的位置来获取用户的天气数据。
- 尝试在你的网站上添加一个在这个链接中找到的天气图:https://openweathermap.org/api。
结论
你可以从OpenWeatherMap网站上获取更多的数据。这对于根据需要定制你的应用程序数据是很有用的。这也包括可以嵌入到网页中的实时天气图。在天气预报中,数据越多越好。