Вопрос заключается в том как именно спарсить расписание.
string url = "https://rsue.ru/raspisanie/";
using (var webClient = new WebClient())
{
var pars = new NameValueCollection();
pars.Add("f", "3");
pars.Add("k", "3");
pars.Add("g", "6");
var response = webClient.UploadValues(url, pars);
string str = System.Text.Encoding.UTF8.GetString(response);
HtmlDocument html = new HtmlDocument();
html.LoadHtml(str);
//с этого момента дописать
HtmlNodeCollection nodes = html.DocumentNode.SelectNodes("//div[@class=\"col-lg-2 col-md-2 col-sm-2\"]");
if(nodes != null)
{
foreach(var node in nodes)
{
var link = node.SelectSingleNode(".//div[@class=\"col-lg-12\"]");
Console.WriteLine(link);
}
}
else
{
Console.WriteLine("Empty");
}
Console.ReadKey();
Ну для начала, вашей "неточностью" (хоть некоторые пишут как и вы), является то, что вы экранируете двойные кавычки, HtmlAgilityPack (HAP) очень хорошо дружит с одинарными. По этому вы смело можете писать .SelectSingleNode(".//div[@class='col-lg-12']").
Далее по самому вопросу. Откройте инструменты разработчика и найдите нужную "ноду", через какое-то время вы увидите всю структуру сайта:
Что мы тут видим?
<div class="container"> - основная нода с нужным нам контентом (их там несколько, учтите это!).
<h1> - название группы.<h1 class="ned"> - вид/тип недель.<div class="row"> - контент этой категории недель.
<div class="col-lg-2 col-md-2 col-sm-2" id="" - отдельно расписание каждого дня.
<div class="col-lg-12" id="nedelya-select"> - название дня недели.<div class="col-lg-12 day"> - контент дня.Дальше расписывать не буду, ибо этого думаю будет достаточно для понятия структуры и того, как с этим работать.
Хорошо, давайте теперь по порядку будет получать нужные нам данные:
Получаем основную ноду:
var container = html.DocumentNode.SelectSingleNode("//div[@class='container' and child::h1[@class='ned']]");
Тут из за того, что сайт имеет несколько <div class="container">, я добавил дополнительную проверку, которая проверяет наличие в дочернем элементе h1 с нужным классом, в итоге мы получим ту ноду, которая:
div с классом container.<h1 class="ned">.Теперь можем двигаться дальше и из полученной ноды вытягивать все остальное.
Получаем названия категорий (черные/нечетные):
var categories = container.SelectNodes("./h1[@class='ned']");
Получаем контент каждой категории:
foreach (var category in categories)
{
var content = category.SelectSingleNode("./following-sibling::div[@class='row']");
}
Мы перебираем полученные заголовки и берем следующую, после них ноду, div с указанным классом. Вообще я думаю это все можно преобразовать в Dictionary для удобства:
var categories = container.SelectNodes("./h1[@class='ned']").ToDictionary(k => k.InnerText, v => v.SelectSingleNode("./following-sibling::div[@class='row']"));
Эта строчка объединяет в себе предыдущие запросы на получение четных и нечетных, а также получения их содержимого. Ключом будет название категории, а значением ключа нужная нам div.
Чтож, можем двигаться дальше...
Получим все дни недели:
foreach (var category in categories)
{
Console.WriteLine(category.Key);
var weekday = category.Value.SelectNodes("./div[@id]");
}
Тут все просто, из каждой полученной категории, забираем все div, которые имеют id (нам сайт его выдает пустой). Поняв принцип, смело можем переработать строку формирования Dictionary, дописав туда необходимый XPath:
var categories = container.SelectNodes("./h1[@class='ned']").ToDictionary(k => k.InnerText, v => v.SelectSingleNode("./following-sibling::div[@class='row']").SelectNodes("./div[@id]"));
Тут я дописал .SelectNodes("./div[@id]") для получения всех дней недели. Наверно у вас появился вопрос "почему не в одну XPath?", отвечу - я без понятия как заставить его забирать только дни недели внутри указанного div, если объединить, то первая категория будет иметь 11 дней недели (все, включая нечетные), а вторая будет иметь только свои.
Ну что-ж, основы я вам вроде показал, дальше я думаю вы сможете без труда сделать сами все, что необходимо.
Напоследок пример вывода названия категории и дней недели:
foreach (var category in categories)
{
Console.WriteLine(category.Key);
foreach (var weekday in category.Value)
{
var name = weekday.SelectSingleNode("./div[starts-with(@id, 'nedelya')]")?.InnerText;
Console.WriteLine($"- {name}");
}
}
Ну и весь код:
private static async Task<string> GetSchedule(int faculty, int course, int group)
{
var url = "https://rsue.ru/raspisanie/";
var postContent = new Dictionary<string, string>
{
["f"] = $"{faculty}",
["k"] = $"{course}",
["g"] = $"{group}",
};
using var client = new HttpClient();
var response = await client.PostAsync(url, new FormUrlEncodedContent(postContent));
return await response.Content.ReadAsStringAsync();
}
public static async void LoadData()
{
var str = await GetSchedule(3, 3, 6);
HtmlDocument html = new HtmlDocument();
html.LoadHtml(str);
var container = html.DocumentNode.SelectSingleNode("//div[@class='container' and child::h1[@class='ned']]");
var categories = container.SelectNodes("./h1[@class='ned']")
.ToDictionary(k => k.InnerText, v => v.SelectSingleNode("./following-sibling::div[@class='row']").SelectNodes("./div[@id]"));
foreach (var category in categories)
{
Console.WriteLine(category.Key);
foreach (var weekday in category.Value)
{
var name = weekday.SelectSingleNode("./div[starts-with(@id, 'nedelya')]")?.InnerText;
Console.WriteLine($"- {name}");
}
}
}
Если планируете и дальше работать с XPath, то советую эту шпаргалку, очень часто меня выручала.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости