27 Aralık 2010 saat: 11:58

Web uygulamaları geliştiren herkesin bir şekilde farklı amaçlar doğrultusunda bot yazma ihtiyacı olmuştur. Bot’lar kullanım amacına göre farklı algoritmalara sahip olabilmektedir. Söz gelimi arama motorlarının “örümcek”  olarak adlandırılan yazılımları aslında sayfaları indeksleme özelliğine sahip olan özel bot’lardır.
Biz bu uygulamamızda küçük çaplı bir bot yazmış olacağız. Amacımız bir web sitesinin sahip olduğu resim bağlantılarını ve mevcut olan linklerini toplamak.
Buradaki mantığı kısaca özetleyecek olursak HTTP protokolünü ve Html dilini kullanan sistemlere .NET yapısının bize sunmuş olduğu ilgili sınıflar aracılığı ile bağlantı kurup, verileri toplamak ve düzenleyip istediğimiz biçimdeki bilgilere dönüştürmek olarak ifade edebiliriz.
Burada toplanan bilgilerin düzenlenmesi aşamasında ilk akla gelen Regex (düzenli ifadeler) olacaktır. Fakat Regex ile bu işi yapmak gerçekten can sıkıcı olabilir. Her farklı yapı için kendi Regex fonksiyonlarımızı oluşturmak biraz zahmetli olacaktır.
Biz burada sıfırdan Regex tanımlamak yerine bu iş için yazılmış olan HtmlAgilityPack kütüphanesini kullanacağız. Bu tarz da ki kütüphaneleri çok özel bir durum olmadığı sürece kullanmanızı tavsiye ederim. Çünkü sizin sıfırdan uğraşarak yapmak istediğiniz birçok fonksiyon bu kütüphanelerin içerisinde daha da gelişmiş olarak zaten mevcut olmaktadır.
Html Parser dediğimiz olay ise aslında toplanan bilgilerin düzenlenmesi aşamasıdır. Biz HtmlAgilityPack kütüphanesi ile toplamış olduğumuz bilgileri istediğimiz biçimde ayrıştırmaya çalışacağız. Yani Html Parse etmiş olacağız.

Bu kısa giriş den sonra dilerseniz uygulamamıza geçebiliriz.
HtmlAgilityPack API’sinin güncel olan sürümünü http://htmlagilitypack.codeplex.com/releases/view/44954 adresinden indiriyoruz ve projemize referans olarak ekliyoruz.
Ben resim ve link bağlantılarını ayrı ayrı elde etmek için form tasarımını aşağıdaki gibi yaptım.

27_12_2010_a1.jpg

Resimleri Ayrıştır ve Linkleri Ayrıştır butonlar’ına tıkladığım zaman ilgili listboxlar da ilgili bağlantı adreslerini almak istiyorum.
Bunun için ilgili siteye öncelikle bir istek de bulunacağız sonrasında siteden gelen cevabı okuyup html formata çevireceğiz. Bu aşamadan sonra html parse işlemleri için HtmlAgilityPack api’sini kullanacağız.

Eklenmesi gereken namespace’ler

27_12_2010_a.jpg
Gerekli kodlarımız ve açıklamaları

28_12_2010_1.jpg

3_1_2011_1.jpg

28_12_2010_3.jpg

 Programımızı çalıştırdıkdan sonra ki ekran görüntümüz.

27_12_2010_a2.jpg

Dikkat ettiyseniz burada pek bir özel tanımlama yapmadan doğrudan tüm resim ve bağlantı linklerini aldık. Dilersek site içerisinde bulunan belli tanımlamalara ait bağlantıları isteğimize göre çekip alabiliriz. Örneğin ünlü Rock grubu Hypnogaja’nın http://www.hypnogaja.com/welcome.html sitesine bakalım. Grubun Here Comes The Rain Again adlı parçasını da dinlemenizi tavsiye ederim. Favori parçalardan biridir.
Burada html tarafında a tag’larına baktığımız zaman bir çoğunda onclick olayı olduğunu ve  onclick="window.open(this.href); return false;" şeklinde tanımlandığını görüyoruz. Bizimde ihtiyacımız olan şey ise bu şekilde tanımlı  linkleri almak olsun. Bunun için tek yapmamız gereken _htmlColl değişkenimize seçme işlemini nasıl yapacağını belirtmek.
İlgili satırı,
28_12_2010_4.jpg
şeklinde tanımladığımızda onclick olayı 'window.open(this.href); return false;' şeklinde olan linkleri çekmiş olacağız.

Hepinize Kolay Gelsin. İyi Çalışmalar.

HtmlParse.rar



kategoriler:  C# |

MSsql veritabanımızda okuma işlemleri yapacağımız zaman ExecuteReader ve ExecuteScalar metodlarını kulanıyoruz. Bu iki metodda sadece select sorgulamalarında çalışmaktadır. Insert, Delete, Update gibi sorgulama işlemlerinde ise ExecuteNonQuery metodunu kullanıyoruz.

ExecuteScalar metodu tek bir değer döndüren sorgulama işlemlerinde kullanılmaktadır. Örneğin belli bir alandaki sayısal değerlerin toplamını veya tablodaki kayıt sayısını veren sorgulamalar gibi.  sum, count, avg, max, min vs. 

ExecuteReader metodu ise select sorgusu ile çektiğimiz verileri satır ve sütün olarak herhangi bir veri kaynağına aktaracağımız durumlarda tercih edilmektedir. Aynı zamanda bu metod ile executescalar gibi tek bir değeri okuma işlemide yapılabilmektedir. Bunun içinde executereader metodunun CommandBehavior.SingleResult parametresi kullanılmaktadır.

Şimdi her ikiside tek bir değeri okuma işlemini gerçekleştiriyor o zaman hangisini kullanmalıyız ?
Yapacağımız örnek uygulamada da bunu öğrenmeye çalışacağız. Burada metodların çalışma zamanını tesbit etmek için Stopwatch sınıfını kullanıcaz. Normalde kodun çalışma zamanını belirlemek için DateTime.Now kullanarak kodun ilk çalışma zamanı ile son çalışma zamanı arasındaki farkı alıyorduk. Stopwatch sınıfı ile bunu daha hassas bir şekilde ölçmüş olacağız.

Örnek Uygulama için aşağıdaki gibi basit bir veritabanı tasarladım. Veritabanımızın ismi deneme ve kisiler tablosuna sahip.

12_11_2010_f1.jpg

File > New > Project  ve yeni bir Console Application oluşturuyoruz. Ve kodlarıda aşağıdaki gibi yazıyoruz. Ben gerekli kısımlara açıklama satırları ekledim.


using
System;

using System.Collections.Generic;

using System.Text;

using System.Data; // ekliyoruz.

using System.Data.SqlClient; // ekliyoruz.

using System.Diagnostics; // Stopwatch sınıfını kullanabilmek için bu namespace'i ekliyoruz.

 

namespace PerformansTest

{

    class Program

    {

        static void Main(string[] args)

        {

            /*ExecuteReader*/

            Stopwatch stpwch = new Stopwatch(); //stopwatch sınıfından stpwch isimli bir değişken oluşturduk.

 

            SqlConnection _con = new SqlConnection(@"Data Source=XP7\XPSEVENSQLSERVER;Initial Catalog=deneme;Integrated Security=True");

            SqlCommand _cmd = new SqlCommand("select*from kisiler", _con);

            _con.Open();

 

            stpwch.Start(); // stpwch değişkeninin ilk çalışma noktası burası.

            SqlDataReader _dr = _cmd.ExecuteReader(CommandBehavior.SingleResult);

            _dr.Read();

            stpwch.Stop(); // stpwch değişkeninin bitiş noktası burası. yani hangi kod aralığının çalışma zamanını kontrol edeceksek ilgili kodların üst ve alt satırlarında çalışma ve bitiş noktasını belirtiyoruz.

 

            Console.WriteLine("ExecuteReader Sonucu:");

            Console.WriteLine("----------------------");

            Console.WriteLine("Okunan Veriler = " + _dr["kisi_ad"].ToString());

 

            _con.Close();

            _dr.Close();

           

            Console.WriteLine("Verilerin okunma süresi = " + stpwch.Elapsed.ToString());

            Console.WriteLine("");

 

            /*ExecuteScalar*/

            Stopwatch stpwch2 = new Stopwatch(); //stopwatch sınıfından stpwch2 isimli bir değişken oluşturduk.

 

            SqlConnection _con2 = new SqlConnection(@"Data Source=XP7\XPSEVENSQLSERVER;Initial Catalog=deneme;Integrated Security=True");

            SqlCommand _cmd2 = new SqlCommand("select * from kisiler", _con2);

            _con2.Open();

 

            Console.WriteLine("");

            Console.WriteLine("ExecuteScalar Sonucu:");

            Console.WriteLine("----------------------");

 

            stpwch2.Start(); // stpwch2 değişkeninin ilk çalışma noktası burası

            Console.WriteLine("Okunan Veriler = " + _cmd2.ExecuteScalar().ToString());

            stpwch2.Stop(); // stpwch2 değişkeninin bitiş noktası burası.

 

            _con2.Close();

 

            Console.WriteLine("Verilerin okunma süresi = " + stpwch2.Elapsed.ToString());

            Console.ReadLine();

 

        }

    }

}

 

 
Projeyi derleyip çalıştırdığımda ekran görüntüsünü aşağıdaki gibi aldım.

12_11_2010_f2.jpg

Ekran çıktısındanda gözüktüğü gibi ExecuteScalar metodu ExecuteReader metodundan yaklaşık 2.5 kat daha hızlı çalışmaktadır. Yalnız bu değerler benim kendi PC kaynaklarıma göre çıkan sonuçlar. Performans değeri daha düşük ya da daha yüksek bir PC üzerinde bu sonuçların değerleri değişebilir. Ama hangi PC olursa olsun çıkan kıyaslama sonucu değişmeyecektir.

Evet Arkadaşlar bu örnekde mssql veritabanından tek bir değeri okurken kullanılan metodların veri okuma hızlarını test etmeye çalıştık.
Faydalı olması umuduyla hepinize kolay gelsin. 
İyi çalışmalar.


kategoriler:  C# |

.NET ortamında yazmış olduğumuz programlarda kullandığımız değişken türleri ikiye ayrılmaktadır. Bunlar değer türleri (value types) ve referans türleri (reference types) dir.

Değer Türleri (Value Types) :
Doğrudan veriyi taşıyan ve taşıdığı veriye göre bellek üzerinde yer dolduran değişken türüdür. Değer türleri bellekte az yer kaplar ve kendilerine hızlı bir şekilde erişilir. Değer türleri belleğin stack dediğimiz kısmında saklanır.

Referans Türleri (Reference Types):
Referans türlerinde aynen değer türlerinde olduğu gibi veri ram üzerinde stack alanında saklanır. Ayrıca ram üzerindeki heap denilen bölgede de verinin (nesnenin) adresini tutar. Burada daha fazla bellek kullanılır ve erişim daha zordur.

Aşağıda değer ve referans türlerine ait temel veri tipleri görülmektedir.

12_11_2010_e1.jpg


Değer türleri ile Referans türleri arasındaki en önemli fark belleğin farklı alanlarında depolanıyor olmalarıdır. Değer türleri stack, referans türleri ise heap alanında tutulur.

Bu iki tür arasındaki diğer bir fark ise; Değer türündeki bir değişkenin değeri başka bir değişkene atanırsa veri değeri kopyalanmış olunur. Referans türünde ise veri değerleri kopyalanmaz sadece bellekte bulunan adresi kopyalanır.

Bu anlattığımız kopyalanma olayını bir örnek üzerinde inceleyelim. Ben formun tasarımını aşağıdaki gibi yaptım.

12_11_2010_e2.jpg

Amacımız değer ve referans türünden oluşturulmuş değişkenlerin değerlerinin bir başka değişkene atandığında meydana gelen değişikliğin neler olduğunu anlamaya çalışmak. Kod tarafına geçiyoruz.

Form1.cs

        private void buttonValue_Click(object sender, EventArgs e)

        {

            int x = 50;
            int y = x;
            y = Convert.ToInt32(textBox1.Text);
            label2.Text = x.ToString();

// y değişkeninin değerine x'i atadıkdan sonra. y değişkeninin alacağı değeri textboxdan girilen değere eşitledik. fakat labela y değerini yazdırmak istediğimiz zaman textboxdan girilen değer yerine 50 değerini yazdı. 

        }

        public class Kopyalama

        {

            int x;
            public int X

            {

                get { return x; }
                set { x = value; }

            }

        }  // ufak bir class tanımlaması yaptık

 

        private void buttonReference_Click(object sender, EventArgs e)

        {

            Kopyalama ref1 = new Kopyalama();           
            ref1.X = 50;
            Kopyalama ref2 = ref1; 
            ref2.X = Convert.ToInt32(textBox2.Text);
            label4.Text = ref1.X.ToString();

            // burada ref1 isminde Kopyalama sınıfından yeni bir nesne türettik ve değerini 50 olarak belirledik. Daha sonra Kopyalama sınıfından ref2 isimli yeni bir nesne türettik ve bunu ref1 nesnesine eşitledik. Sonrasında ref2 nesnesinin değerini textboxdan girilecek olan değere eşitledik. Bu sefer ilk verilen değer yerine textboxdan girilen değer gösterildi.

        }

12_11_2010_e3.jpg

Şimdi nerede ne oldu onu anlamaya çalışalım. Biz burada x isimli değişkeni y isimli değişkene kopyaladıktan sonra stack üzerinde y için ayrı bir alan ayrıldı. Böylece her iki değişken birbirini etkilemeyerek farklı bellek adreslerinde tutuldu.
ref1 değişkeni ref2 değişkenine kopyalandığı zaman başvurulan nesnenin kendisi değil adresi ref2'ye kopyalanmış oldu. Böylece stack üzerinde farklı adreslerde bulunan ref1 ve ref2 değişkenleri aynı yeri ve heap üzerinde bulunan aynı adresi (Kopyalama nesnesinin yeri) göstermiş oldu.

Evet arkadaşlar bu yazımda değer ve referans türlerinin ne anlama geldiğini ve ram üzerinde hangi alanlarda saklandıklarını anlatmaya çalıştım.
Hepinize kolay gelsin. İyi çalışmalar.

 

kategoriler:  C# |