Парсер цен на топливо за текущий день
Сегодня попробуем написать простой парсер цен на топливо за сегодняшний день. В качестве источника информации будем использовать сайт Передовых Платежных Решений. Почему именно его, просто случайность. Регион для сбора сведений — Республика Татарстан. И самое главное — язык программирования C# (не все же время писать на PHP )
Для начала создадим новый проект под названием dsGasPriceParser. На проекте расположим форму с тремя Label (имена lbl95, lbl92 и lblDt). Кстати, посмотреть результат работы можно на рис. 1. Я форму немного приукрасил.
Рис. 1. Пример запущенного приложения
Принцип работы программы довольно прост. Сначала осуществляется запрос на определенный URL, откуда вытягивается все содержимое страницы (https://www.petrolplus.ru/fuelindex/tatarstan_republic/
). После при помощи класса для работы с регулярными выражениями Regex ищем нужные нам строки. Так информация о ценах на странице представлена в виде графика, то за его построение отвечает javascript. Вот как раз из данного скрипта мы и будем извлекать данные.
В результате получаем данные для бензина 92 и 95, а также дизельного топлива.
Сразу приведу весь текст программы файла основной формы (frmMain.cs).
using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.IO; using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; namespace dsGasPriceParser { public partial class frmMain : Form { // Файл для хранения данных private static string filename = AppDomain.CurrentDomain.BaseDirectory + @"\dsGasPriceParser"; // Ссылка для парсинга данных private static string sourceUrl = "https://www.petrolplus.ru/fuelindex/tatarstan_republic/"; public frmMain() { InitializeComponent(); } private static void getData(string url) { List<string> list = new List<string>(); string html = getRequest(url); string pattern = @"(('АИ-\d{2}')|('Дизельное топливо'))+" + @"(,data:\s)+" + @"\[(.*)\]+"; Regex regex = new Regex(pattern); MatchCollection matches = regex.Matches(html); foreach (Match math in matches) { string Prices = math.Groups[5].ToString(); string[] Price = Prices.Split(','); double newPrice = double.Parse(Price[6], CultureInfo.InvariantCulture); list.Add(String.Format("{0:0.00}", newPrice)); } try { // Запись в файл File.WriteAllLines(filename, list); } catch { MessageBox.Show("Неудалось записать файл", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private static string getRequest(string url) { try { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.AllowAutoRedirect = false; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream stream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream, Encoding.GetEncoding(response.CharacterSet))) { return reader.ReadToEnd(); } } } } catch { return String.Empty; } } private void Form1_Load(object sender, EventArgs e) { if (File.Exists(filename)) { DateTime creationTime = File.GetLastWriteTime(filename); if (DateTime.Now.ToShortDateString() != creationTime.ToShortDateString()) { getData(sourceUrl); } } else { getData(sourceUrl); } // Считывание файла string[] lines = File.ReadAllLines(filename); lbl95.Text += ": " + lines[0] + "р."; lbl92.Text += ": " + lines[1] + "р."; lblDt.Text += ": " + lines[2] + "р."; } private void panel1_Paint(object sender, PaintEventArgs e) { ControlPaint.DrawBorder( e.Graphics, e.ClipRectangle, Color.FromKnownColor(KnownColor.ControlLightLight), 1, ButtonBorderStyle.Solid, Color.FromKnownColor(KnownColor.ControlLightLight), 1, ButtonBorderStyle.Solid, Color.FromKnownColor(KnownColor.ControlDark), 1, ButtonBorderStyle.Solid, Color.FromKnownColor(KnownColor.ControlDarkDark), 1, ButtonBorderStyle.Solid); } private void panel2_Paint(object sender, PaintEventArgs e) { ControlPaint.DrawBorder( e.Graphics, e.ClipRectangle, Color.FromKnownColor(KnownColor.ControlLightLight), 1, ButtonBorderStyle.Solid, Color.FromKnownColor(KnownColor.ControlLightLight), 1, ButtonBorderStyle.Solid, Color.FromKnownColor(KnownColor.ControlDark), 1, ButtonBorderStyle.Solid, Color.FromKnownColor(KnownColor.ControlDarkDark), 1, ButtonBorderStyle.Solid); } private void panel3_Paint(object sender, PaintEventArgs e) { ControlPaint.DrawBorder( e.Graphics, e.ClipRectangle, Color.FromKnownColor(KnownColor.ControlLightLight), 1, ButtonBorderStyle.Solid, Color.FromKnownColor(KnownColor.ControlLightLight), 1, ButtonBorderStyle.Solid, Color.FromKnownColor(KnownColor.ControlDark), 1, ButtonBorderStyle.Solid, Color.FromKnownColor(KnownColor.ControlDarkDark), 1, ButtonBorderStyle.Solid); } private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { System.Diagnostics.Process.Start("https://sitkodenis.ru"); } } }
Чтобы каждый раз не обращаться на сайт и тем самым сэкономить ресурсы, информацию о ценах на бензин сохраняем в файл dsGasPriceParser в текущем каталоге программы. Это обычный текстовый файл, в котором цена записаны каждая с новой строки.
Путь к файлу хранится в поле filename, а источник, откуда берется информация располагается в поле sourceUrl.
Событие panel1_Paint() необходимо лишь для отрисовки элементов управления Panel (можно просто удалить данное событие, тем более, если не используете данные элементы управления в своей программе).
Событие Form1_Load() обрабатывается при загрузке единственной формы и проверяет, если текущая дата совпадает с датой создания файла, то просто считываем данные из файла dsGasPriceParser. Однако, если дата создания отличается, то выполняется метод getData(sourceUrl).
Метод getData() используется для получения данных о ценах на топливо. Здесь как можно увидеть в переменной pattern хранится шаблон для поиска данных. Все найденные строки все еще содержат не нужную информацию, поэтому мы извлекаем только цены math.Groups[5].ToString()
. Кстати, можно текст АИ-95 и т.п. получить из спарсенных данных. Я посчитал все это излишним и решил хранить только цены. Дополнительно задаем форматирование для наших цен, чтобы все выглядело одинаково. При необходимости, сохраняем изменения или создаем файл с ценами на топливо.
Метод getRequest() — стандартное обращение к странице для получения ее содержимого.
Для удобства выкладываю исходный код программы: dsGasPriceParser.
Вот таким не сложным путем был сделан парсер цен на топливо за текущее число. При извлечение информации можно было еще отсечь лишнее, но я уж оставил так как есть. Тем более работа с регулярными выражениями — это уже отдельная история.
Спасибо за внимание и до новых встреч!
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.