HtmlAgilityPack ile html parsing – C#

Geçtiğimiz günlerde html parsing ile ilgili küçük bir program yapmagerekiyordu. Biraz araştırdıktan daha önce de olduğu gibi html parsing içinde codeplex'te bir kütüphane bulmuştum. (we <3 codeplex) Bu yazıda Html Agility Pack kullanarak basit bir parser'ın nasıl yapılacağı hakkında bilgi vermek istiyorum. Öncelikle yeni bir windows application oluşturup Nuget Package Manager'dan HtmlAgilityPack paketini projeye referans ediyoruz. Ya da isterseniz buradan dll olarak indirip projeye ekleyebilirsiniz. Örnek uygulamayı buradan indirebilirsiniz. 

İlk olarak indirmek ve parse etmek istediğimiz sayfayı belirlememiz ve hangi bilgileri parsing ile almak istediğimizi belirlemeliyiz. Örnek olarak http://www.w3schools.com/htmldom/default.asp bu sayfadaki "Html Dom Refrence" , "Html Dom Example" gibi alt başlıkları çekmek istiyorum. Sayfanın source kısmına baktığımızda bu başlıkların aşağıdaki gibi html kodu olduğunu görüyoruz.

<h2 class="tutheader">HTML DOM Reference</h2>

Buradaki h2 etiketi class="tutheader" özelliği bizim seçici özelliklerimiz olacak.

Şimdi Form'a bir buton ve bir listbox ekleyelim. Butonun click olayı ile siteye request gönderip, html bilgilerini çekeceğiz ve sonra da parse edip başlıkları listbox içinde göstereceğiz.

 

private void button1_Click(object sender, EventArgs e) 
{
     Uri url = new Uri("http://www.w3schools.com/htmldom/default.asp");
     WebClient client = new WebClient();
     string html = client.DownloadString(url);     
    // Adresten istek yapı html kodlarını indiriyoruz.     
    
    HtmlAgilityPack.HtmlDocument dokuman = new HtmlAgilityPack.HtmlDocument();     
    dokuman.LoadHtml(html);     
    // İndirdiğimiz html kodlarını bir HtmlDocment nesnesine yüklüyoruz.     
    HtmlNodeCollection basliklar = dokuman.DocumentNode.SelectNodes("//h2[@class='tutheader']");     
    // Html dökümanı içndeki h2 etiketlerinden class'ı  tutheader olanları liste halinde alıyoruzç     
    foreach (var baslik in basliklar)     
    {         
        listBox1.Items.Add(baslik.InnerText);     
        // Biraz önceki basliklar koleksiyonunu tek tek gezerek, her bir elemanının içindeki text'i alıyoruz     
    }
}

Yukarıdaki kodların altında açıklamalarımı yazdığım için tekrar açıklamaya gerek duymuyorum. Burada önemli olan şey çekeceğinzi bilgilerin hangi tag içinde ve hangi özellikte olduğunu bilmeniz. Mesela burada html kodunda class="tutheader" değil de id="tutheader" şeklinde bir özellik olabilirdi. Bu durumda seçeceğimiz node'u aşağıdaki şekilde belirlerdik.

dokuman.DocumentNode.SelectNodes("//h2[@id='tutheader']")

Projeyi çalıştırdığınızda butona tıkladıktan 4-5 saniye sonra istediğimiz bilgileri listbox içinde görebiliyoruz. Bu arada form 4-5 saniyeliğine kilitleniyor. Eğer buton içindekiğ kodları bir thread ile çalıştırırsanız bu kilitlenme de ortadan kalkacaktır.

13 thoughts on “HtmlAgilityPack ile html parsing – C#

    • Yakup Buğra Post authorReply

      Kütüphanenin kendisinden kaynaklandığını zannetmiyorum. Sunucunuzun ayarları ile ilgili olmalı.

  1. Kemal Can ÖZÇELİK Reply

    Bende aynı şekilde türkçe karakter sorunu yaşadım bulduğum çözüm en basit yoldu :) Aşağıdaki hazırladığım method'a string'i gönder yeter dahada karakter eklenebilir eksikleri gördükçe tamamlarsınız.

    public string ReplaceText(string _text)
    {
     _text = _text.Replace("Ä°", "İ").Replace("ı", "ı").Replace("Ã&frac14;", "ü").Replace("ÅŸ", "ş").Replace("Å", "Ş").Replace("ç", "ç").Replace("ö", "ö").Replace("ÄŸ", "ğ").Replace("Ç", "Ç").Replace("Ö", "Ö").Replace("Ãœ", "Ü");
      return _text;
    }

     

    Kolay gelsin.

    • Kerem Reply

      Merhaba Kemal. Çözümün doğru fakat daha kolay bir yolu var ve paylaşmak istedim sıkıntı çekmeyin diye. "string html=" diye başlayan satırın üstüne yani "client" nesnesinin altına "client.Encoding = System.Text.Encoding.UTF8;" yazarsanız sorunu çözmüş olacaksınız :) Herkese kolay gelsin, başarılar…

  2. Burak Reply

    Çektiğim tag aralıklarını direk webbrowser.documenttext e aktarmak istiyorum nasıl yapabilirim

    baslik.innerhtml e eşitlediğimde en son satırı aktarıyor.

    • Yakup Buğra Post authorReply

      en son satırdan kastınız nedir?

  3. ugur Reply

    string html=… satırından önce:

    "client.Encoding = System.Text.Encoding.GetEncoding(1254);" eklerseniz Türkçe karakter sorunu çözülür.

  4. Furkan Reply

    Foreach döngüsünde;Nesne başvurusu bir nesnenin örneğine ayarlanmadı. hatası alıyorum

    • Yakup Buğra Post authorReply

      debug’dayken kontrol edin büyük ihtimalle forech’te içinde döndüğünüz nesne null geliyor

  5. Hakan Reply

    Kodu bu şekilde kullandığımda türkçe karakterlerde problem yaşadım. Bende dosyayı webClient ile açmak yerine WebRequest ve WebResponse sınıfları ile bağlanıp stream ile açtım:

                Uri site = new Uri("http://borsaistanbul.com/&quot;);
                WebRequest wrq = WebRequest.Create(site);

                WebResponse wrs = wrq.GetResponse();

                Stream stream = wrs.GetResponseStream();

                StreamReader reader = new StreamReader(stream);
                string html = reader.ReadToEnd();
                    

                HtmlAgilityPack.HtmlDocument dokuman = new HtmlAgilityPack.HtmlDocument();
                
                dokuman.LoadHtml(html);

Leave a Reply

Your email address will not be published. Required fields are marked *