Analiza Parsowanie HTML-a  nie jest prostą sprawą. HTML nie ma jednolitej składni i nie może być potraktowany jak plik XML. Napisanie swojego parsera też nie jest łatwe. Analiza HTML przy użyciu wyrażeń regularnych jest jeszcze gorszym koszmarem.

Na szczęście jak to w programowaniu bywa ktoś już dużo wcześniej opracował rozwiązanie i się z nim podzielił. W tym wpisie omówię bibliotekę HTMLAgilityPack.

Aby użyć tej biblioteki nie trzeba odwiedzać strony CodePlex. Paczkę można pobrać przy użyciu NuGet-a.

image

Co oferuje ta biblioteka? Napiszę program który pobierze moją stronę internetową po czym z jej zawartości stworze listę słów.

Używając metody Load z HTMLAgilePack możemy uzyskać obiekt HtmlDocument który określi na zawartość strony w podobny sposób do obiektu XMLDocument.

private static HtmlDocument RetrieveHtml(string WebsiteUrl)
{
    HtmlWeb hw = new HtmlWeb();
    return hw.Load(WebsiteUrl);
}

Mając już ten obiekt operujemy na nim przy pomocy metod LINQ dokładnie tak samo jak z obiektem XMLDocument.  Poniższe wyrażenie LINQ wyrwa zawartość tekstową z dokumentu HTML.

private HtmlDocument d;
List<string> list = new List<string>();

private  void btnGetSite_Click(object sender, RoutedEventArgs e)
{
    d = RetrieveHtml(txtSiteUrl.Text);

    var text = d.DocumentNode.Descendants()
        .Where(x => x.NodeType == HtmlNodeType.Text && x.InnerText.Trim().Length > 10
            && !(x.InnerHtml.Trim().Contains("function")) && !(x.InnerHtml.Trim().Contains("![CDATA["))
            && !(x.InnerHtml.Trim().Contains("var")) && !(x.InnerHtml.Trim().Contains("http://"))
            && !(x.InnerHtml.Trim().Contains("SyntaxHighlighter"))
            && !(x.InnerHtml.Trim().Contains("class"))
            )
        .Select(x => x.InnerText.Trim());


    foreach (var a in text.Select(var2 => var2.Split(' ')))
    {
        for (int i = 0; i < a.Length; i++)
        {
            a[i] = Regex.Replace(a[i], "[^a-zA-Zęńśćąóżźł]+", "");

            if (a[i] != "" && a[i].Length >= 5)
            {
                list.Add(a[i]);

            }
        }
    }

    lbWords.ItemsSource = list;
}

Później  zawartość tekstowa jest rozbijana na pojedyncze słowa. Przy pomocy odpowiedniego wyrażenia regularnego upewniam się ,że słowa nie zawierają w sobie niedozwolonych znaków.

Jeśli wyraz jest dłuższy bądź równy niż 5 znaków jest on wtedy dodawany do listy.

image

Prawda ,że było to proste.

Edit z 2022: Kod jest na GitHubie : PanNiebieski/HtmlParseExampleWPF (github.com)