JavaRush /Java Blog /Random-TW /我們在幾個晚上為 Telegram 創建了一個簡單的天氣機器人
Philip J.
等級 40
Днепр

我們在幾個晚上為 Telegram 創建了一個簡單的天氣機器人

在 Random-TW 群組發布
大家好!為 Telegrams 創建機器人的主題有些陳詞濫調,並且已經編寫了很多指南(例如,這個。因此,我們最好仔細研究使用一些第三方 API,因為這對於任何 Web 開發人員來說都是一項關鍵技能。我馬上就會說,該應用程式並沒有打算提供最實用、最有用的預報;與天氣網站競爭是沒有意義的;學習如何使用 Java 進行遠端連接和資料解析非常重要。所以,我們首先要弄清楚我們需要什麼。我們的應用程式本質上由三個邏輯部分組成:
  • 接受用戶的消息
  • 處理該訊息,如果它是有效命令,則為回應準備資料。在我們的例子中,如果使用者輸入了正確的城市,則準備天氣預報
  • 在聊天中向用戶發送準備好的信息
第一點和第三點非常簡單,只涉及使用 Telegram API;有興趣的可以研究上面留下的連結。我們重點關注第二點。當一些開發人員想要向其他開發人員提供對其資料的存取權限時,就會使用 API。我們以 VKontakte 為例。每個人都有一個朋友列表,它儲存在 VK 伺服器上的資料庫中的某個位置。假設某個程式設計師決定與朋友一起創建一個跳棋遊戲。為了讓他的應用程式正常運作,該程式必須能夠獲取任何玩家的好友清單。為此,程式設計師會尋找 VK API 的文件並查看需要發出哪些請求才能取得此清單。此請求稱為 HTTP 請求。最常見的兩個 HTTP 請求是 GET 和 POST。網路上也有足夠多的內容,我不會阻止你。對於我們的目的,即獲取天氣預報數據,一個簡單的 GET 請求就足夠了。如果我們向常規 Web 伺服器發出 GET 請求,它通常會傳回 html 程式碼,瀏覽器會將其轉換為使用者友好的頁面,套用樣式、腳本等。如果我們向 API 伺服器發出這樣的請求,則回應通常只會傳回原始數據,沒有樣式和腳本。在瀏覽器視窗中,它看起來像這樣: 我們在幾個晚上為 Telegram 創建了一個簡單的天氣機器人 - 1該數據不是為人們準備的,而是為其他程式準備的,因此,除了資訊本身之外,這些頁面中沒有任何額外的內容。原始資料通常使用以下兩種標準之一傳送:JSON 或 XML。每種方法都有其優點和缺點,但是了解兩者很重要。您已經在上面的螢幕截圖中看到了 JSON,而 XML 如下所示:經過 我們在幾個晚上為 Telegram 創建了一個簡單的天氣機器人 - 2簡短搜索,找到了英文版 Open Weather Map 項目,如果您每分鐘發出的請求不超過 50 個,該項目將免費提供資料。這對我們來說已經足夠了,我們註冊,我們收到一個獨特的令牌(代碼),伺服器透過它知道我們不是冒名頂替者,而是正派的未來開發人員。我們進入API文件( tyts )頁面,發現透過發送表單請求可以獲得任何城市5天的天氣預報。
https://api.openweathermap.org/data/2.5/forecast?q=(город)&APPID=(уникальный токен, полученный при регистрации)
您可以在瀏覽器中看到對此類請求的回應。我們 已經發現,事實上,您只需點擊正確的鏈接,伺服器就會提供必要的資料。剩下的就是學習如何使用 Java 來完成此操作。Java 中的簡單 GET 請求如下所示:
//создаём строку со ссылкой на нужную page,
//я тут её склеиваю из заранее определённых констант, меняя только сам город
String urlString = API_CALL_TEMPLATE + city + API_KEY_TEMPLATE;
//создаём an object который будет содержать ссылку
URL urlObject = new URL(urlString);
//создаём соединение, используя an object
HttpURLConnection connection = (HttpURLConnection) urlObject.openConnection();
//выбираем тип requestа (GET)
connection.setRequestMethod("GET");
//тут мы указываем, данные о себе, что мы можем принять всё то,
//что примет и любой современный браузер
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
//В начало ответа server всегда вставляет число, по которому можно судить, прошло ли всё хорошо.
//200 - значит OK
int responseCode = connection.getResponseCode();
//на несуществующий город or город с опечаткой, server выдаст code ответа 404,
//бросаем на него исключение, чтобы обработать на уровне повыше и предложить
//пользователю ввести город заново
if (responseCode == 404) {
     throw new IllegalArgumentException();
}
// создаём поток, вычитываем все строки, и склеиваем в одну большую строку,
//которую будем потом обрабатывать в других методах
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
     response.append(inputLine);
}
in.close();
return response.toString();
如果請求正確且伺服器可用,我們將收到一張數據,其中有用的信息與現在不需要的資訊混合在一起。為了方便地從 JSON 和 XML 中提取必要的數據,已經為 Java 編寫了大量的庫來滿足各種需求。由於我更喜歡 JSON,所以我選擇了一個非常流行的庫 Jackson 來處理它。順便說一句,在 JavaRush 中對它進行了一些高水平的研究。要處理大量 JSON 數據,了解文件的結構非常重要。像這樣的有用網站可以拯救你。左邊是原始 JSON,右邊是結構化 JSON: 我們在幾個晚上為 Telegram 創建了一個簡單的天氣機器人 - 3 可以看出,回應由 5 個頂層 JSON 物件組成,其中 2 個很複雜,是以下分支的節點。我們感興趣的資料儲存在清單節點中。內部列表是由 38 行 JSON 行組成的數組,每行描述特定時間的天氣。也就是說,它是一種樹狀結構,有根、樹枝、細枝甚至葉子:)並且在節點處發生分支。幸運的是,Jackson 可以將任何有效的 JSON 表示為樹。因此,知道我們需要的屬性的名稱(例如,氣溫)以及它位於樹的哪一層,取得它就不成問題了。首先,我從“list”數組中提取所有行並將它們添加到單獨的列表中。粗略地說,我將包含資料的工作表切成了幾塊,每塊都是一個單獨的預測。小零件更容易記住和操作。
//JsonNode - это один из узлов в древовидной иерархии, от которого идут ветви
//получаем узел, который называется "list"
JsonNode arrNode = new ObjectMapper().readTree(data).get("list");
//если это действительно массив узлов
if (arrNode.isArray()) {
//выполняем для каждого узла, который содержится в массиве
      for (final JsonNode objNode : arrNode) {
//в атрибуте "dt_txt" каждого маленького узла хранилось время прогноза, я отобрал данные за 9 утра и 6 вечера
                String forecastTime = objNode.get("dt_txt").toString();
                if (forecastTime.contains("09:00") || forecastTime.contains("18:00")) {
                weatherList.add(objNode.toString());
            }
      }
}
這樣我們就得到了一個字串列表,其中每一行代表某個時間的 JSON 天氣預報。剩下的就是提取您想要的內容並對其進行格式化。如果我們有這樣一行:
"main":{"temp":261.45,"temp_min":259.086,"temp_max":261.45,"pressure":1023.48,"sea_level":1045.39,"grnd_level":1023.48,"humidity":79,"temp_kf":2.37}
那麼這是一個名為「main」的節點。要從中取得任何數據,例如海平面,以下程式碼就足夠了:
ObjectMapper objectMapper = new ObjectMapper();
//line - это наша JSON-строка
mainNode = objectMapper.readTree(line).get("main");
String seaLevel = mainNode.get("sea_level");
Jackson 讓您立即以數字格式表示資料:
double seaLevel = mainNode.get("sea_level").asDouble();
現在我們可以從預測中提取任何數據,剩下的就是根據需要將其粘合在一起並將其發送給 Telegram 中的用戶。完整的源代碼位於我的github上,但您可以使用連結嘗試運行該機器人,或在 Telegram 搜尋中尋找 @denifoBot。城市名稱必須用拉丁文語音譯書寫,例如「基輔」或「莫斯科」。謝謝,如果你堅持到了最後,我接受合理的批評,因為我只是在 GitHub 上學習和開發簡單的項目,以便與我所在城市的飢餓人才競爭:) 大家再見!PS我相信這裡可能有錯字,所以你可以在私人訊息中發送所有內容,或者如果你真的很生氣,也可以在評論中發送:)
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION