#c# #asp.net-mvc #html-agility-pack
#c# #asp.net-mvc #html-пакет гибкости
Вопрос:
Я хочу экспортировать свой план запуска Asic в iCal, и поскольку Asic не предлагают эту услугу, я решил создать небольшой scraper для своего личного использования. Что я хочу сделать, так это взять все запланированные запуски из моего плана и сгенерировать на их основе канал iCal. Я использую C # и пакет гибкости Html.
Что я хочу сделать, так это повторить все мои запланированные запуски (они являются узлами div). Затем я хочу выбрать несколько разных узлов с моими узлами запуска. Мой код выглядит следующим образом:
foreach (var run in doc.DocumentNode.SelectSingleNode("//div[@id='scheduleTable']").SelectNodes("//div[@class='pTdBox']"))
{
number ;
string date = run.SelectSingleNode("//div[@class='date']").InnerText;
string type = run.SelectSingleNode("//span[@class='menu']").InnerHtml;
string distance = run.SelectSingleNode("//span[@class='distance']").InnerHtml;
string description = run.SelectSingleNode("//div[@class='description']").InnerHtml;
ViewData["result"] = "Dato: " date "<br />";
ViewData["result"] = "Tyep: " type "<br />";
ViewData["result"] = "Distance: " distance "<br />";
ViewData["result"] = "Description: " description "<br />";
ViewData["result"] = run.InnerHtml.Replace("<", "amp;<").Replace(">", "amp;>") "<br />" "<br />" "<br />";
}
Моя проблема в том, что run.SelectSingleNode("//div[@class='date']").InnerText
не выбирает узел с заданным XPath в пределах данного запущенного узла. Выбирается первый узел, который соответствует XPath во всем документе.
Как я могу выбрать единственный узел с заданным XPath в текущем узле?
Спасибо.
Обновить
Я попытался обновить свою строку XPath до этого:
string date = run.SelectSingleNode(".div[@class='date']").InnerText;
Это должно выбрать <div class="date"></div>
элемент внутри текущего узла, верно? Ну, я попробовал это, но получил эту ошибку:
Выражение должно соответствовать набору узлов. Описание: Необработанное исключение возникло во время выполнения текущего веб-запроса. Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.
Сведения об исключении: System.Xml.XPath.XPathException: Выражение должно соответствовать набору узлов.
Есть предложения?
Комментарии:
1. Я не уверен (вообще) в XPath, но не
//
означает ли это, что где-либо из root?2. w3schools.com/xpath/xpath_axes.asp : Мне кажется, вам нужно что-то вроде
child::div[@class='data']
, но опять же, я не знаю наверняка. Вообще.
Ответ №1:
Несколько вещей, которые помогут вам при работе с выражениями HtmlAgilityPack и XPath.
Если run
является HtmlNode
, то:
-
run.SelectNodes("//div[@class='date']")
Будет вести себя точно так же, какdoc.DocumentNode.SelectNodes("//div[@class='date']")
-
run.SelectNodes("./div[@class='date']")
Предоставит вам все<div>
узлы, которые являются дочерними элементамиrun
узла. Он не будет искать глубже, только на самом следующем уровне глубины. -
run.SelectNodes(".//div[@class='date']")
Вернет все<div>
узлы с этим атрибутом класса, но не только рядом сrun
узлом, но и проведет углубленный поиск (во всех возможных его потомках)
Вам придется выбирать между 2. или 3., в зависимости от того, какой из них удовлетворяет вашим потребностям 🙂
Комментарии:
1. Боже, ты просто спас мне жизнь. Я просто перепутал между 1 и 3. Спасибо, чувак.
2. @Soren Со мной случилось то же самое 🙂
Ответ №2:
В XPATH //
означает всех дочерних и внучатых дочерних элементов ниже текущего узла. Итак, вам нужно придумать более строгое выражение XPATH. Если вы предоставите реальный HTML-код и именно то, что вы ищете, мы можем помочь вам копать дальше.
Об ошибке, которая у вас:
.div[@class='date']
недопустимо, потому что .
привязано к div
. Вы могли бы использовать div[@class='date']
, или ./div[@class='date']
которые, я считаю, эквивалентны. Это потому, что .
это XPATH axe, который является псевдонимом для self
и означает «текущий узел».
Комментарии:
1. @Simon Mourier — Я также пытаюсь получить данные с узла, имеющего атрибут «name», но он их не принимает
2. @студент — тебе следует написать другой вопрос