JavaRush /בלוג Java /Random-HE /אנו יוצרים בוט מזג אוויר פשוט לטלגרם בעוד כמה ערבים
Philip J.
רָמָה
Днепр

אנו יוצרים בוט מזג אוויר פשוט לטלגרם בעוד כמה ערבים

פורסם בקבוצה
שלום לכולם! הנושא של יצירת בוטים עבור טלגרם הוא קצת פרוע, ונכתבו הרבה מדריכים (למשל, זה ) . לכן, מוטב שנבחן מקרוב את העבודה עם ממשק API של צד שלישי, מכיוון שזו מיומנות קריטית עבור כל מפתח אינטרנט. אני אגיד מיד שהאפליקציה לא התכוונה לספק את התחזית הפונקציונלית והשימושית ביותר; אין טעם להתחרות באתרי מזג אוויר; היה חשוב ללמוד כיצד לעבוד עם חיבורים מרוחקים וניתוח נתונים באמצעות Java. אז בואו נגלה מה אנחנו צריכים קודם. האפליקציה שלנו מורכבת בעיקרה משלושה חלקים לוגיים:
  • קבל הודעה מהמשתמש
  • לעבד את ההודעה, ואם היא פקודה חוקית, להכין נתונים לתגובה. במקרה שלנו, הכינו תחזית מזג אוויר אם המשתמש נכנס לעיר הנכונה
  • לשלוח מידע מוכן למשתמש בצ'אט
הנקודה הראשונה והשלישית די פשוטות, והן נוגעות רק לעבודה עם ה-API של טלגרם; המעוניינים יכולים ללמוד את הקישור שמשמאל למעלה. נתמקד בנקודה השנייה. ממשקי API משמשים כאשר מפתחים מסוימים רוצים לספק גישה לנתונים שלהם למפתחים אחרים. ניקח לדוגמא את VKontakte. לכל אחד יש רשימת חברים, היא מאוחסנת איפשהו במסד נתונים בשרתי VK. נניח שאיזה מתכנת החליט ליצור משחק דמקה עם חברים. כדי שהאפליקציה שלו תעבוד כהלכה, על התוכנית להיות מסוגלת להשיג את רשימת החברים של כל שחקן. לשם כך, המתכנת מוצא את התיעוד עבור ה-API של VK ובוחן איזו בקשה צריכה להיעשות כדי לקבל רשימה זו. בקשה זו נקראת בקשת HTTP. ושתי בקשות ה-HTTP הנפוצות ביותר הן GET ו-POST. יש גם מספיק עליהם באינטרנט, אני לא אעצור אותך. למטרותינו, כלומר השגת נתוני תחזית מזג האוויר, תספיק בקשת GET פשוטה. אם נבצע בקשת GET לשרת אינטרנט רגיל, לרוב הוא יחזיר קוד html, אותו הדפדפן ממיר לעמוד ידידותי למשתמש, תוך החלת סגנונות, סקריפטים וכו'. אם נגיש בקשה כזו לשרת ה-API, התגובה הוא בדרך כלל רק נתונים גולמיים מוחזרים ללא סגנונות וסקריפטים. בחלון הדפדפן זה נראה בערך כך: אנו יוצרים בוט מזג אוויר פשוט לטלגרם בעוד כמה ערבים - 1הנתונים האלה לא מיועדים לאנשים, אלא לתוכנות אחרות, כך שאין שום דבר נוסף בדפים כאלה מלבד המידע עצמו. נתונים גולמיים נשלחים לרוב באמצעות אחד משני סטנדרטים: JSON או XML. לכל אחד יש את היתרונות והחסרונות שלו, עם זאת, חשוב להבין את שניהם. כבר ראיתם את JSON בצילום המסך למעלה, ו-XML נראה כך: אנו יוצרים בוט מזג אוויר פשוט לטלגרם בעוד כמה ערבים - 2לאחר חיפוש קצר, נמצא פרויקט Open Weather Map בשפה האנגלית, המספק נתונים בחינם אם לא תבצעו יותר מ-50 בקשות לדקה. זה מספיק לנו, אנחנו נרשמים, אנחנו מקבלים אסימון (קוד) ייחודי שלפיו השרת יידע שאנחנו לא מתחזים, אלא מפתחים עתידיים הגונים. אנחנו עוברים לדף עם תיעוד ה-API ( tyts ), ומגלים שניתן לקבל תחזית של 5 ימים לכל עיר על ידי שליחת בקשה של הטופס.
https://api.openweathermap.org/data/2.5/forecast?q=(город)&APPID=(уникальный токен, полученный при регистрации)
אתה יכול לראות איך נראית התגובה לבקשה כזו בדפדפן, כבר גילינו שלמעשה אתה רק צריך לעקוב אחר הקישור הנכון והשרת יספק את הנתונים הדרושים. כל מה שנותר הוא ללמוד כיצד לעשות זאת באמצעות Java. בקשת GET פשוטה ב-Java נראית כך:
//создаём строку со ссылкой на нужную 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 המקורי, מימין - המובנה: אנו יוצרים בוט מזג אוויר פשוט לטלגרם בעוד כמה ערבים - 3 ניתן לראות שהתגובה מורכבת מ-5 אובייקטי JSON ברמה עליונה, 2 מהם מורכבים ומהווים צמתים לענפים הבאים. הנתונים שאנו מעוניינים בהם מאוחסנים בצומת הרשימה . הרשימה הפנימית היא מערך של 38 קווי JSON, כל אחד מתאר את מזג האוויר בזמן מסוים. כלומר, זה מעין מבנה דמוי עץ, שבו יש שורש, ענפים, זרדים ואפילו עלים :) ובצמתים מתבצעת ההסתעפות. למרבה המזל, ג'קסון יכול לייצג כל JSON חוקי כעץ. לפיכך, לדעת את שם התכונה שאנו צריכים (לדוגמה, טמפרטורת האוויר), ובאיזו רמה של העץ היא ממוקמת, קבלתה לא תהיה בעיה גדולה. ראשית, חילצתי את כל השורות ממערך ה"רשימה" והוספתי אותן לרשימה נפרדת. בגדול, חתכתי את הגיליון עם הנתונים לחתיכות שכל אחת מהן היא תחזית נפרדת. קל יותר לזכור ולפעול איתם חלקים קטנים.
//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}
אז זהו צומת שנקרא "ראשי". כדי לקבל ממנו נתונים כלשהם, למשל פני הים, מספיק הקוד הבא:
ObjectMapper objectMapper = new ObjectMapper();
//line - это наша JSON-строка
mainNode = objectMapper.readTree(line).get("main");
String seaLevel = mainNode.get("sea_level");
ג'קסון מאפשר לך לייצג מיד נתונים בפורמט מספרי:
double seaLevel = mainNode.get("sea_level").asDouble();
כעת נוכל לחלץ כל נתון מהתחזית, וכל שנותר הוא להדביק אותו כרצוי ולשלוח למשתמש בטלגרם. קוד המקור המלא נמצא ב- github שלי , אבל אתה יכול לנסות את הבוט בפעולה באמצעות הקישור , או על ידי מציאת @denifoBot בחיפוש הטלגרם. יש לכתוב את שם העיר בתעתיק לטיני, למשל "קייב" או "מוסקבה". תודה, אם הגעת עד הסוף, אני מקבל ביקורת סבירה, שכן אני רק לומד ומפתח פרויקטים פשוטים ב-GitHub כדי להתחרות עם כישרונות רעבים מהעיר שלי :) ביי כולם! נ.ב אני מאמין שאולי יש כאן שגיאות הקלדה, אז את יכולה לשלוח הכל בהודעה פרטית, או בתגובה אם את ממש כועסת :)
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION