Парсер цен на топливо на текущий день

Сегодня попробуем написать простой парсер цен на топливо за сегодняшний день. В качестве источника информации будем использовать сайт Передовых Платежных Решений. Почему именно его, просто случайность. Регион для сбора сведений — Республика Татарстан. И самое главное — язык программирования C# (не все же время писать на PHP smile )

Для начала создадим новый проект под названием dsGasPriceParser. На проекте расположим форму с тремя Label (имена lbl95, lbl92 и lblDt). Кстати, посмотреть результат работы можно на рис. 1. Я форму немного приукрасил.

dsGasPriceParserРис. 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.

Добавить комментарий

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: