🧪 Практикум: парсинг диалогов DeepSeek с помощью C# и регулярных выражений

C# Regex Парсинг DeepSeek

🎯 Цель практикума: Научиться извлекать сообщения из диалога с DeepSeek, используя только C# и регулярные выражения, без сторонних библиотек.

📌 Шаг 1. Сохраняем диалог с DeepSeek

Чтобы получить данные для парсинга, нам нужно сохранить страницу с диалогом в формате HTML.

Инструкция:

  1. Откройте chat.deepseek.com в браузере.
  2. Авторизуйтесь и откройте нужный диалог.
  3. Нажмите Ctrl + S (или Cmd + S на Mac).
  4. Выберите тип сохранения: «Веб-страница полностью» (HTML + файлы) или «Веб-страница, только HTML».
  5. Назовите файл deepseek_chat.html и сохраните в удобную папку.
🔍 Если DeepSeek подгружает сообщения динамически (при скролле):

Прокрутите страницу вниз до конца диалога, чтобы все сообщения загрузились, и только потом сохраняйте.

📌 Шаг 2. Анализируем структуру HTML

Откройте сохранённый файл deepseek_chat.html в любом редакторе кода (VS Code, Notepad++, даже в Блокноте).

Найдите блоки сообщений. В DeepSeek они обычно выглядят так:

<div class="chat-message user">
  <div class="message-text">Привет, DeepSeek!</div>
</div>

<div class="chat-message assistant">
  <div class="message-text">Здравствуйте! Чем могу помочь?</div>
</div>

Ключевые элементы для регулярного выражения:

📌 Шаг 3. Пишем регулярное выражение для парсинга

Нам нужно извлечь две вещи: роль (user или assistant) и текст сообщения.

// Шаблон с именованными группами
string pattern = @"<div class=""chat-message\s+(?<role>user|assistant)"">\s*<div class=""message-text"">(?<text>.*?)</div>";

Разбор паттерна:

Часть шаблонаЧто означает
<div class=""chat-message\s+Открывающий тег с классом chat-message и пробелом
(?<role>user|assistant)Именованная группа role — user или assistant
>\s*<div class=""message-text"">Закрывающий тег и открывающий тег текста
(?<text>.*?)Именованная группа text — текст сообщения (ленивый захват)
</div>Закрывающий тег текста
💡 Совет: Используйте флаг RegexOptions.Singleline, чтобы точка (.) учитывала переводы строк. И RegexOptions.Compiled для производительности.

📌 Шаг 4. Пишем полный код на C#

Создайте новое консольное приложение в Visual Studio или VS Code. Вставьте следующий код:

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;

class DeepSeekParser
{
  // Регулярное выражение для парсинга сообщений
  private static readonly Regex MessageRegex = new Regex(
    @"<div class=""chat-message\s+(?<role>user|assistant)"">\s*<div class=""message-text"">(?<text>.*?)</div>",
    RegexOptions.Singleline | RegexOptions.Compiled
  );

  public static List<ChatMessage> ParseFromHtml(string html)
  {
    var messages = new List<ChatMessage>();
    var matches = MessageRegex.Matches(html);

    foreach (Match match in matches)
    {
      string role = match.Groups["role"].Value;
      string text = match.Groups["text"].Value;
      // Декодируем HTML-сущности
      text = text
        .Replace("&lt;", "<")
        .Replace("&gt;", ">")
        .Replace("&amp;", "&")
        .Replace("&quot;", "\"");
      messages.Add(new ChatMessage
      {
        Role = role == "user" ? MessageRole.User : MessageRole.Assistant,
        Text = text
      });
    }
    return messages;
  }

  public static void SaveToFile(List<ChatMessage> messages, string filePath)
  {
    using (var writer = new StreamWriter(filePath))
    {
      foreach (var msg in messages)
      {
        writer.WriteLine($"[{msg.Role}] {msg.Text}");
        writer.WriteLine(new string('-', 50));
      }
    }
  }
}

public class ChatMessage
{
  public MessageRole Role { get; set; }
  public string Text { get; set; }
}

public enum MessageRole { User, Assistant }

class Program
{
  static void Main()
  {
    // Укажите путь к сохранённому HTML-файлу
    string html = File.ReadAllText("deepseek_chat.html");

    var messages = DeepSeekParser.ParseFromHtml(html);

    // Выводим в консоль
    foreach (var msg in messages)
    {
      Console.WriteLine($"{msg.Role}: {msg.Text}");
    }

    // Сохраняем в файл
    DeepSeekParser.SaveToFile(messages, "chat_output.txt");

    Console.WriteLine($"\n✅ Сообщений распаршено: {messages.Count}");
  }
}

📌 Шаг 5. Запускаем и проверяем

Порядок действий:

  1. Положите deepseek_chat.html в ту же папку, где находится Program.cs.
  2. Запустите программу (F5 в Visual Studio или dotnet run).
  3. В консоли увидите список сообщений с ролями User и Assistant.
  4. В папке появится файл chat_output.txt с тем же содержимым.

📌 Шаг 6. Задания для самостоятельной работы

🔹 Задание 1. Извлечение ссылок из сообщений

Добавьте в программу дополнительный парсинг: найдите все URL-ссылки (http:// или https://) внутри текста сообщений и выведите их отдельно.

// Подсказка:
string urlPattern = @"https?://[^\s/$.?#].[^\s]*";

🔹 Задание 2. Подсчёт статистики

Посчитайте и выведите в консоль:

  • Общее количество сообщений
  • Количество сообщений от пользователя
  • Количество сообщений от ассистента
  • Среднюю длину сообщения (в символах)

🔹 Задание 3. Обработка пустых сообщений

В диалогах могут встречаться пустые или служебные сообщения. Добавьте проверку: если текст сообщения пустой или содержит только пробелы — не добавлять его в результат.

📌 Шаг 7. Возможные проблемы и их решение

ПроблемаРешение
Файл deepseek_chat.html не найден Укажите полный путь к файлу или переместите файл в папку с проектом
Regex не находит сообщения Откройте HTML и убедитесь, что классы совпадают. Если DeepSeek изменил структуру — поправьте регулярное выражение
Текст содержит странные символы (&lt;, &gt;) Убедитесь, что вы добавили замену HTML-сущностей (код в шаге 4)
Сообщения отображаются в неправильном порядке Проверьте, что в HTML они идут в том же порядке, что и в диалоге. Regex сохраняет порядок.

📌 Итоги практикума

Вы научились:

🚀 Что дальше?

Попробуйте применить этот же подход для парсинга других сайтов: извлечения цен с маркетплейсов, новостей, комментариев — везде, где есть структурированный HTML.

📚 Больше материалов по C# и парсингу — на gadget59.ru