Parsowanie dokumentu HTML w .NET

Pewnie nie raz zastanawialiście się jak szybko i bez nadmiernego wysiłku wyciągnąć informacje z dokumentu HTML. Niedomknięty znacznik czy brak apostrofów to już standard w większości stron. XHTML po części rozwiązuje niektóre problemy, ale stron w pełni walidowanych też za dużo nie uświadczymy. Mimo podobieństw większość stron HTML nie  możemy traktować jak dokumentów XML. Platforma .NET nie dostarcza nam narzędzi do parsowania dokumentów HTML, pozostaje nam wiec korzystanie z zewnętrznych bibliotek.

W niniejszym wpisie chciałbym przedstawić bibliotekę którą poznałem już jakiś czas temu: Html Agility Pack, która nie raz już ułatwiła mi pracę. Główną zaletą tej biblioteki jest możliwość poruszanie sie po dokumencie HTML jak po dokumencie XML. Do wybierania elementów dokumentu mozemy uzyci języka XPath lub korzystając z LINQ (od wersji 1.4.0). Sam proces używania i posługiwania się wspomnianą biblioteką jest dość prosty i pokrótce zaprezentują go poniżej.

Oczywiście pierwszą czynnością jaką musimy wykonać aby móc korzystać z tej biblioteki jest dodanie do projektu referencji do pliku HTMLAgilityPack.dll. Po tej czynnosci mozemy korzystac z elementow jakie dostarcza nam biblioteka.

Klasą reprezentującą nasz dokument HTML jest HtmlDocument. Obiekt tej klasy tworzymy korzystając z domyślnego konstruktora.

WebClient client = new WebClient();
string html = client.DownloadString("");

HtmlDocument doc = new HtmlDocument();

Dokument HTML możemy wczytać korzystając z metody Load do której możemy przekazać strumień, obiekt klasy TextReader lub ścieżkę do pliku. Alternatywą jest użycie medody LoadHtml, którą wykorzystałem w powyższym przykładzie, wczytującej dokument bezpośrednio z obiektu klasy System.String. Przed wczytaniem dokumentu możemy ustawić odpowiednie opcje parsowania ustawiając odpowiednie wartości polom o nazwach w formacie:  OptionsXXX.

W celu pobranie błędów parsowania korzystamy z  dostępnej właściwości ParseErrors:

Console.WriteLine("Parse errors:");
foreach(HtmlParseError error in doc.ParseErrors)

Główny węzeł dokumentu dostępny jest pod właściwością DocumentNode korzystając z tego obiektu możemy przeglądać kolejne węzły wczytanego dokumentu. W celu pobrania elementu na podstawie identyfikatora używamy metody GetElementbyId.

HtmlNode blogDescription = doc.GetElementbyId("blog-description");
if(blogDescription != null)
Console.WriteLine("Blog description: {0}",blogDescription.InnerText);

Jeśli chcemy wyszukać konkretne węzły w naszym dokumencie możemy skorzystać z LINQ:

IEnumerable<HtmlNode> links = from link in doc.DocumentNode.DescendantNodes()
where link.Name == "a" && link.Attributes["href"] != null
select link;

IEnumerable<HtmlNode> links2 = doc.DocumentNode.DescendantNodes()
.Where(x=>x.Name == "a" && x.Attributes["href"] != null);

lub wykorzystując język XPath:

HtmlNodeCollection xpathLinks =

foreach(var link in links)

Najnowszą wersję opisywanej biblioteki można znaleźć na stronie

Projekt demonstrujący wykorzystanie HtmlAgilityPack można pobrać tutaj.

25,115 thoughts on “Parsowanie dokumentu HTML w .NET”

  1. 即日でも即引越

  2. I have read so many articles or reviews concerning the blogger
    lovers but this post is truly a pleasant paragraph, keep
    it up.

  3. of course like your web site however you have
    to check the spelling on several of your posts.
    Many of them are rife with spelling problems and I in finding it
    very bothersome to tell the truth then again I will certainly come back

  4. That is very fascinating, You are a very professional blogger.
    I have joined your feed and look forward to seeking extra of your magnificent post.
    Additionally, I have shared your site in my social networks

  5. I really like what you guys tend to be up too. This kind of clever work and reporting!
    Keep up the awesome works guys I’ve added you guys to my blogroll.

  6. Do you mind if I quote a couple of your posts as long as I provide credit and sources back to
    your site? My website is in the very same niche as yours and my visitors would genuinely benefit from some of the information you
    provide here. Please let me know if this alright with you.

  7. Howdy! Would you mind if I share your blog with my facebook group?
    There’s a lot of people that I think would
    really enjoy your content. Please let me know.
    Thank you

  8. Usually I don’t read article on blogs, however I would like to say that this write-up very forced me
    to take a look at and do so! Your writing taste has been surprised me.

    Thank you, quite great post.

  9. Howdy just wanted to give you a quick heads up. The text in your content seem to
    be running off the screen in Opera. I’m not sure if this is a format issue or something to do with web browser compatibility but I figured I’d
    post to let you know. The style and design look great though!
    Hope you get the problem resolved soon. Many thanks

  10. Usually I don’t learn post on blogs, but I would like to say that
    tuis write-up very forced mee to check outt and do it! Your
    writing style has been amazed me. Thanks, quite great article.

  11. Boutіqu de vente d arme plur l’autⲟdéfense. Taser
    Électrique, matrаque , bombe ԁe defense a petit ргix.
    retrouvez également notre largе gamme de poings américains, couteaux, et armes de defense pour femme.

  12. Generally I don’t learn article on blogs, however I wish to say that this write-up
    very forced me to try and do it! Your writing style has been amazed me.

    Thank you, quite nice post.

  13. certainly like your web-site but you need to test the spelling on quite a few of your
    posts. Many of them are rife with spelling issues and I in finding it very troublesome to inform the
    reality then again I will certainly come back again.

  14. I had hoped for a water birth at my birth center with my husband by my side; my son came early and very fast – my husband ended up rushing back from a business trip to Europe and I had an unplanned home birth! When my doula arrived to take me to the birth center, she could already see the head! (I hadn’t realized I was already fully dilated and past transition.)

  15. There are plenty of strappy and strapless wedding dresses out there, but
    you rarely see any single-strap styles. The
    cartoon is set in wat iis left of the make-believe continent known as the
    Land of Ooo in the aftermath. Present participles: Present participles are formed bby adding ing at tthe
    endd of a verb. We will take a look at a number of distinct fancy dress options to help give you a picture
    of some of tthe stules that you can pick from should you need to go burlesque
    for an night. Pair this floral delight with heeled sandals and an eye-catching necklace to complete the look.
    Having a predecided dresscode for the office makes items muuch simpler.
    Among thhe formal clothing, navvy blue iis the most preferred

  16. This noticed the event of bows, flowers, rhinestones, plastic-sort material
    jewellery and even navy period by 1950 to 1959 was simply
    the place jewelry has develop into extra conventional and complicated.
    This was an times where a dress was not total without the acceptable necklace,
    lapel inexperienced, bracelet or possibly earrings.

  17. I like the valuable information you provide to your articles.

    I will bookmark your blog and take a look at again right here regularly.
    I’m moderately sure I’ll be informed many new stuff proper right here!
    Best of luck for the following!

  18. I am really happy to read this webpage posts which contains lots of helpful data,
    thanks for providing these kinds of information.

  19. Hello there, I believe your web site may be having browser compatibility issues.

    Whenever I look at your site in Safari, it looks fine however, when opening in IE, it has some overlapping
    issues. I just wanted to give you a quick heads up! Other than that,
    fantastic blog!

  20. godt du fik besked om graveriet i skuret, og at det ikke var rotter. Det var ikke for at gøre dig nervøs. Men vi opdagede det meget sent (altsÃ¥ at vi havde rotter i skuret) og sÃ¥ var der altsÃ¥ mange af dem. SÃ¥ det var for at du opdagede det før. Men det var sÃ¥ ikke rotter og heldigvis.Lyder til at du og Rufus har hygget jer pÃ¥ landet. hav en god weekend 🙂

Leave a Reply