Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Created June 3, 2026 09:05
Show Gist options
  • Select an option

  • Save sunmeat/9ebc72323c408650e6756106e6e2409d to your computer and use it in GitHub Desktop.

Select an option

Save sunmeat/9ebc72323c408650e6756106e6e2409d to your computer and use it in GitHub Desktop.
парсинг HTML з використанням регулярок на С++ (версія для мак ос)
#include <iostream>
#include <string>
#include <regex>
#include <vector>
#include <cstdio>
#include <cstdlib>
using namespace std;
// https://wttr.in/odesa
string read_file(const string& path) {
FILE* file = fopen(path.c_str(), "rb");
if (!file) return "";
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
fseek(file, 0, SEEK_SET);
if (file_size <= 0) {
fclose(file);
return "";
}
string content(file_size, '\0');
fread(&content[0], 1, file_size, file);
fclose(file);
return content;
}
// завантажує URL у файл через curl (замість URLDownloadToFileA на Windows)
bool download_file(const string& url, const string& out_path) {
string cmd = "curl -s -o \"" + out_path + "\" \"" + url + "\"";
return system(cmd.c_str()) == 0;
}
string extract(const string& text, const string& pattern) {
smatch m;
if (regex_search(text, m, regex(pattern)))
return m[1].str();
return "";
}
string decode_entities(const string& s) {
string r = regex_replace(s, regex("&#47;"), "/");
r = regex_replace(r, regex("&nbsp;"), " ");
r = regex_replace(r, regex("&quot;"), "\"");
r = regex_replace(r, regex("&amp;"), "&");
r = regex_replace(r, regex("&lt;"), "<");
r = regex_replace(r, regex("&gt;"), ">");
return r;
}
string translate_desc(const string& desc) {
vector<pair<string, string>> translations = {
{"Sunny", "Сонячно"},
{"Clear", "Ясно"},
{"Clear sky", "Ясно"},
{"Mainly clear", "Переважно ясно"},
{"Partly cloudy", "Мінлива хмарність"},
{"Mostly cloudy", "Переважно хмарно"},
{"Cloudy", "Хмарно"},
{"Overcast", "Суцільна хмарність"},
{"Patchy rain nearby", "Місцями дощ"},
{"Patchy rain possible", "Можливий місцями дощ"},
{"Rain", "Дощ"},
{"Light rain", "Невеликий дощ"},
{"Moderate rain", "Помірний дощ"},
{"Heavy rain", "Сильний дощ"},
{"Light drizzle", "Слабка мряка"},
{"Drizzle", "Мряка"},
{"Freezing drizzle", "Крижана мряка"},
{"Freezing rain", "Крижаний дощ"},
{"Sleet", "Мокрий сніг"},
{"Light snow", "Невеликий сніг"},
{"Moderate snow", "Помірний сніг"},
{"Heavy snow", "Сильний сніг"},
{"Blizzard", "Завірюха"},
{"Blowing snow", "Заметіль"},
{"Snow shower", "Снігопад"},
{"Light snow showers", "Невеликі снігопади"},
{"Snow", "Сніг"},
{"Thunder", "Гроза"},
{"Thunderstorm", "Гроза"},
{"Thundery outbreaks", "Можливі грози"},
{"Fog", "Туман"},
{"Mist", "Імла"},
{"Haze", "Димка"},
{"Ice pellets", "Крупа"},
{"Windy", "Вітряно"},
{"Strong winds", "Сильний вітер"},
{"Storm", "Шторм"},
{"Tropical storm", "Тропічний шторм"},
// Російськомовні варіанти
{"Солнечно", "Сонячно"},
{"Ясно", "Ясно"},
{"Малооблачно", "Мінлива хмарність"},
{"Переменная облачность", "Мінлива хмарність"},
{"Облачно", "Хмарно"},
{"Пасмурно", "Суцільна хмарність"},
{"Дождь", "Дощ"},
{"Небольшой дождь", "Невеликий дощ"},
{"Слабый дождь", "Невеликий дощ"},
{"Умеренный дождь", "Помірний дощ"},
{"Сильный дождь", "Сильний дощ"},
{"Ливень", "Злива"},
{"Морось", "Мряка"},
{"Снег", "Сніг"},
{"Небольшой снег", "Невеликий сніг"},
{"Снегопад", "Снігопад"},
{"Метель", "Завірюха"},
{"Сильная метель", "Сильна завірюха"},
{"Гроза", "Гроза"},
{"Туман", "Туман"},
{"Сильный туман", "Густий туман"},
{"Дымка", "Димка"},
{"Крупа", "Крупа"},
{"Град", "Град"},
{"Ветрено", "Вітряно"},
{"Шторм", "Шторм"}
};
for (const auto& p : translations) {
if (desc.find(p.first) != string::npos)
return p.second;
}
return desc;
}
void show_weather(const string& city, const string& city_label) {
string url = "https://wttr.in/" + city;
string file = "/tmp/wttr_" + city + ".html"; // на macOS пишемо у /tmp замість поточної папки
if (!download_file(url, file)) {
cerr << "Помилка завантаження для: " << city_label << "\n";
return;
}
string html = read_file(file);
if (html.empty()) {
cerr << "Не вдалося прочитати файл для: " << city_label << "\n";
return;
}
string block = extract(html, "<div class=\"term-container\">([\\s\\S]*?)</div>");
if (block.empty()) {
cerr << "Дані не знайдено для: " << city_label << "\n";
return;
}
block = decode_entities(block);
string desc_raw = extract(block, "> ([A-Z][a-z A-Z]+)\\n");
string temp_main = extract(block, "<span[^>]*>([+-]?\\d+)</span>\\(");
string temp_feel = extract(block, "\\(<span[^>]*>([+-]?\\d+)</span>\\)");
string wind_speed = extract(block, "term-fg1\">[^<]+</span>\\s*<span[^>]*>(\\d+)</span>");
string description = translate_desc(desc_raw);
string sign_main = (!temp_main.empty() && temp_main[0] != '-' && temp_main[0] != '+') ? "+" : "";
string sign_feel = (!temp_feel.empty() && temp_feel[0] != '-' && temp_feel[0] != '+') ? "+" : "";
cout << "+------------------------------------------+\n";
cout << "| " << city_label << "\n";
cout << "+------------------------------------------+\n";
cout << " Стан: " << description << "\n";
cout << " Температура: " << sign_main << temp_main << " C"
<< " (відчувається " << sign_feel << temp_feel << " C)\n";
cout << " Вітер: " << wind_speed << " км/год\n\n";
}
int main() {
cout << "=== Погода в Україні ===\n\n";
cout << "Завантажуємо дані...\n\n";
vector<pair<string, string>> cities = {
{ "odesa", "Одеса" },
{ "kharkiv", "Харків" },
{ "zhytomyr", "Житомир" },
// додайте інші міста за бажанням
};
for (const auto& c : cities)
show_weather(c.first, c.second);
cout << "Введіть назву свого міста (бажано латиницею):\n";
string user_city;
getline(cin, user_city);
if (!user_city.empty())
show_weather(user_city, user_city);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment