HtmlAgilityPack wählt Daten vom Unterknoten aus

c# html html-agility-pack linq parsing

Frage

Ich habe den folgenden HTML-Code, den ich analysieren möchte:

<h3 class='bar'>
  <a href='http://anysite.com/index.php?showuser=7195' title='Profile view'>THIS_IS_USERNAME</a>
  &nbsp;
  <a href='http://anysite.com/index.php?showuser=7195&amp;f=' class='__user __id7195' title='Profile view'>
      <img src='http://anysite.com/public/style_images/car/user_popup.png' alt='' />
   </a>
</h3>

Was ich hier brauche, ist den Benutzernamen ("THIS_IS_USERNAME") und den Link zum Profil (" http://anysite.com/index.php?shusus=7195 ") zu wählen

Ich kann den oberen h3-Knoten mit dem nächsten Code auswählen:

List<HtmlNode> resultSearch = HTMLPage.DocumentNode.Descendants()
                .Where(
                         x => x.Name.Equals("h3")
                         && x.Attributes["class"] != null
                         && x.Attributes["class"].Value.Equals("bar")                         
                      )
                .ToList();

Aber wie kann ich nicht den "h3" -Knoten selbst, sondern "a" innerhalb von "h3" mit diesem Attribut-Link bekommen, der den Benutzernamen und den Link zum Profil enthält, den ich brauche?

Akzeptierte Antwort

Sie können den Link-Knoten direkt abfragen, er ist mit dem Attribut "Titel" sehr markant.

In diesem Fall ist es wahrscheinlich einfacher, einen XPath zu verwenden, da er alle Zwischen-Nulltests behandelt, und er ist genauso typsicher, da die Linq-Abfrage viele konstante Strings enthält:

var node = HTMLPage.DocumentNode.SelectSingleNode("//hr[@class='Bar']/a[@title='Profile View' and @href");
if (node != null)
{
    string link = node.Attributes["href"].Value;
    string username = node.InnerText;
}

Sie können ähnlichen Code mit der Linq-Syntax schreiben, er sucht zuerst das Link-Tag und dann Backtracks, um einen h3-Elternteil dafür zu finden. Auf diese Weise müssen Sie nicht nach Zwischennulls suchen;):

var node = HtmlPage.DocumentNode.Descendants("a")
    .Where(a =>
        a.Ascendants("h3")
            .Any(h3 =>
                h3.Attributes["class"] != null 
                && a.Attributes["class"].Value == "bar"
            )
    )
    .Where(a => 
        a.Attributes["title"] != null 
        && a.Attributes["title"].Value == "Profile View"
        && a.Attributes["href"] != null
    )
    .FirstOrDefault();

if (node != null)
{
    string link = node.Attributes["href"].value;
    string username = node.InnerText;
}

Oder Sie können die Position verwenden, die das erste <a> Kind von "bar" ist:

// the call to First() will throw an exception if the h3 isn't found.
// returning an empty HtmlNode will allow you to ignore that

var node = (HtmlPage.DocumentNode.Descendants("h3")
    .FirstOrDefault( h => 
            h3.Attributes["class"] != null 
            && a.Attributes["class"].Value == "bar")
    ) ?? HtmlPage.CreateElement("h3")) 
    .Elements("a").FirstOrDefault();

if (node != null)
{
    string link = node.Attributes["href"].value;
    string username = node.InnerText;
}


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum