سلام به همه! موضوع ایجاد ربات برای تلگرام تا حدودی هک شده است و راهنماهای زیادی نوشته شده است (مثلا این یکی ). بنابراین، بهتر است نگاهی دقیقتر به کار با برخی از API های شخص ثالث داشته باشیم، زیرا این یک مهارت حیاتی برای هر توسعه دهنده وب است. فوراً می گویم که برنامه برای ارائه کاربردی ترین و مفیدترین پیش بینی تنظیم نشده است؛ رقابت با سایت های آب و هوا فایده ای ندارد؛ یادگیری نحوه کار با اتصالات از راه دور و تجزیه داده ها با استفاده از جاوا مهم بود. بنابراین، بیایید ابتدا دریابیم که به چه چیزی نیاز داریم. برنامه ما اساسا از سه بخش منطقی تشکیل شده است:
- پذیرفتن پیام کاربر
- پیام را پردازش کنید، و اگر یک دستور معتبر است، داده ها را برای پاسخ آماده کنید. در مورد ما، در صورتی که کاربر شهر صحیح را وارد کرده باشد، پیش بینی آب و هوا تهیه کنید
- ارسال اطلاعات آماده به کاربر در چت
https://api.openweathermap.org/data/2.5/forecast?q=(город)&APPID=(уникальный токен, полученный при регистрации)
شما می توانید ببینید که چگونه پاسخ به چنین درخواستی در مرورگر به نظر می رسد. ما قبلاً متوجه شده ایم که در واقع فقط باید پیوند صحیح را دنبال کنید و سرور داده های لازم را ارائه می دهد. تنها چیزی که باقی می ماند این است که یاد بگیرید چگونه این کار را با استفاده از جاوا انجام دهید. یک درخواست 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، هزاران کتابخانه برای جاوا نوشته شده است تا با هر سلیقه ای مطابقت داشته باشد. از آنجایی که من JSON را ترجیح می دادم، یک کتابخانه بسیار محبوب به نام جکسون را برای پردازش آن انتخاب کردم. ضمناً در JavaRush در برخی سطوح بالا کمی مطالعه شده است. برای پردازش مقادیر زیادی از داده های JSON، درک ساختار سند مهم است. سایت های مفیدی مانند این به کمک می آیند . در سمت چپ ما JSON اصلی را داریم، در سمت راست - ساختار یافته: می توان دید که پاسخ از 5 شیء سطح بالای JSON تشکیل شده است که 2 تای آنها پیچیده هستند و گره هایی برای شاخه های زیر هستند. داده های مورد علاقه ما در گره لیست ذخیره می شود . فهرست داخلی آرایه ای از 38 خط JSON است که هر کدام آب و هوا را در زمان خاصی توصیف می کنند. یعنی نوعی ساختار درخت مانند است که در آن ریشه، شاخه، شاخه و حتی برگ وجود دارد :) و در گره ها انشعاب صورت می گیرد. خوشبختانه، جکسون می تواند هر 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}
سپس این یک گره به نام "اصلی" است. برای دریافت هر گونه داده از آن، به عنوان مثال سطح دریا، کد زیر کافی است:
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 برای رقابت با استعدادهای گرسنه شهرم هستم :) خداحافظ همه! PS من فکر می کنم که ممکن است در اینجا اشتباهات املایی وجود داشته باشد، بنابراین شما می توانید همه چیز را در یک پیام خصوصی یا در یک نظر اگر واقعا عصبانی هستید ارسال کنید :)
GO TO FULL VERSION