Вопрос заключается в том как именно спарсить расписание.
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, то советую эту шпаргалку, очень часто меня выручала.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
У меня есть CanvasНа нем есть некое поле Field и в нем объект Aim
Имеется проблема с визуализацией в MetroUIЕсли в MetroTabControl создать MetroPanel, и в параметре Dock поставить заполнение, то появляются такие полоски
С наступающим! (для всех, читающих в 2020 - с наступившим!) )
После обновления версии mysql по этой статье и перезагрузки сервера, перестало заходить по старым доступам в бд и на сайтах пишет нет подключения...