Написать запрос для анализа HTML-ДОКУМЕНТА с помощью HtmlAgilityPack

#c# #html #linq #html-agility-pack

#c# #HTML #linq #html-agility-pack

Вопрос:

Я хочу получить A href этого элемента в span class=»floatClear», рейтинг которого минимален в
span class=»star-img stars_4″

Как я могу использовать HtmlAgilityPack для достижения такого поведения, я указал html-источник моего файла

 <div class="businessresult">  //will repeat


      <div class="rightcol">

       <div class="rating">

        <span class="star-img stars_4">
          <img height="325" width="84" src="http://media1.px" alt="4.0 star rating"   **title**="4.0 star rating">
         </span>

        </div>
      </div>

        <span class="floatClear">
             <a class="ybtn btn-y-s" href="/writeareview/biz/KaBw8UEm8u6war_loc%NY">
        </span>
</div>
  

Запрос, который я написал

 var lowestreview = 
      from main in htmlDoc.DocumentNode.SelectNodes("//div[@class='rightcol']") 
       from rating in htmlDoc.DocumentNode.SelectNodes("//div[@class='rating']")
         from ratingspan in htmlDoc.DocumentNode.SelectNodes("//span[@class='star-img stars_4']")
          from floatClear in htmlDoc.DocumentNode.SelectNodes("//span[@class='floatClear']")
       select new { Rate = ratingspan.InnerText, AHref = floatClear.InnerHtml };
  

Но я не знаю, как применить условие здесь, в последней строке запроса LINQ!

Комментарии:

1. Вы уверены, что это правильный запрос? Вы выбираете кучу независимых узлов: вы получаете все «рейтинговые» подразделения, независимо от того, находятся они в пределах div «rightcol» или нет (и так далее).

2. Я не уверен в этом, вот почему я спрашиваю!

3. Обязательно ли это должно быть в одном запросе?

4. в этом нет необходимости, мне просто нужно проанализировать html и получить URL-адрес самого низкого просмотренного продукта.

Ответ №1:

Не выбирайте «рейтинг» из всего htmlDoc, выберите его из ранее найденного «main».

Я думаю, вам нужно что-то вроде:

 var lowestreview = 
  from main in htmlDoc.DocumentNode.SelectNodes("//div[@class='rightcol']") 
   from rating in main.SelectNodes("//div[@class='rating']")
     from ratingspan in rating.SelectNodes("//span[@class='star-img stars_4']")
      from floatClear in ratingspan.SelectNodes("//span[@class='floatClear']")
   select new { Rate = ratingspan.InnerText, AHref = floatClear.InnerHtml };
  

Я надеюсь, что это не приведет к сбою, если некоторые из этих разделов и диапазонов отсутствуют: предыдущая версия HtmlAgilityPack возвращала null вместо пустого списка, когда SelectNodes ничего не было найдено.

РЕДАКТИРОВАТЬ
Вероятно, вам также необходимо изменить «запрос xpath» для внутренних выборок: измените «//» на «.//» (дополнительно. в начале), чтобы сигнализировать, что вам действительно нужен подузел. Если AgilityPack работает так же, как обычный XML-XPath (я не уверен на 100%), то «//» в начале будет выполняться поиск из корня документа, даже если вы укажете его из подузла. A «.//» всегда будет выполнять поиск с узла, с которого вы выполняете поиск.

A main.SelectNodes("//div[@class='rating']") (вероятно) также найдет <div class="rating"> s за пределами <div class="rightcol"> того, что вы нашли в предыдущей строке. main.SelectNodes(".//div[@class='rating']") Это должно быть исправлено.

Комментарии:

1. Я думаю, что 2-я последняя строка должна быть из floatClear в htmlDoc. DocumentNode. SelectNodes(«//span[@class=’floatClear’]») // поскольку floatclear не является вспомогательным узлом rightcol div. Также в EDIT вы упоминаете о замене // на what is it (.//)