Google, Bing, Yahoo gibi arama motorları, internetteki sayfaları indexlemek için web crawler denilen programcıklar kullanırlar.
Crawler’ların çalışma mantığı basittir;
Yazacağımız uygulamada, bir web crawler gibi sayfadaki linkleri bulacağız.
Ekran görüntüsündeki formu oluşturduktan sonra, Buton‘un Click olayına ait kodu yazmaya başlayalım.
private void btnLinkleriBul_Click(object sender, EventArgs e) { WebRequest wr = WebRequest.Create(txtAdres.Text); WebResponse ws = wr.GetResponse(); StreamReader sr = new StreamReader(ws.GetResponseStream(), Encoding.UTF8); string response = sr.ReadToEnd(); sr.Close(); ws.Close();
Regex r = new Regex("<a.+href=\"http.+://(.+)\">(.*)</a>");
foreach (Match m in r.Matches(response))
{
string link = m.Groups[1].Value;
if (link.IndexOf("\"") > -1)
link = link.Substring(0, link.IndexOf("\""));
string metin = m.Groups[2].Value;
ListViewItem oItem = new ListViewItem(new string[] { metin, link });
lvSonuc.Items.Add(oItem);
} }</pre> [Code Challenge #1](http://www.enginpolat.com/code-challenge-1/) ve [C# ile Google PageRank Bulma](http://www.enginpolat.com/csharp-ile-google-pagerank-bulma/) yazılarında kullandığım tekniğin aynısı ile sayfanın içeriğini string değişkene alıyoruz.
WebRequest wr = WebRequest.Create(txtAdres.Text); WebResponse ws = wr.GetResponse(); StreamReader sr = new StreamReader(ws.GetResponseStream(), Encoding.UTF8); string response = sr.ReadToEnd(); sr.Close(); ws.Close(); Daha sonra, *Regex* sınıfından yeni bir örnek oluşturup (constructer'ına verdiğimiz parametre önemli), dönen sonuç kümesinin içeriğini *ListView* kontrolüne dolduruyoruz. Eğer sayfanın içeriğini tuttuğumuz değişkeni veritabanına yazsak, ve sayfada bulduğumuz her link için bu adımları tekrar yapsak, tam bir web crawler uygulaması yazmış olacaktık. Ama bu noktadan itibaren uygulamayı geliştirmeyi size bırakıyorum (BilgeAdam'daki öğrencilerime hep dediğim gibi, "Bundan sonrası size ödev!") Projenin bu halini şuradan indirebilirsiniz.
Google‘ın PageRank uygulaması, web sitelerinin Google tarafından önemini bulmakta kullanılan bir algoritmadır.
Wikipedia’daki şu adresten, PageRank algoritması ile ilgili ayrıntılı bilgiye erişebilirsiniz.
Siz de sitenizin PageRank değerini http://www.prchecker.info adresinden bulabilirsiniz.
Yazacağımız uygulama ile, sitenizin Google PageRank değerini programatik olarak buldurabileceğiz.
Google sitelerin PageRank değerlerini, http://toolbarqueries.google.com/search adresine gönderilen sorgulara cevap olarak verebiliyor. Fakat sonuç alabilmemiz için bu adrese doğru parametreleri vermemiz gerekiyor, aksi halde HTTP403 : Forbidden hatası alıyoruz.
Parametreler:
Yukarıdaki resimde görünen arayüzü hazırladıktan sonra, projemize GooglePageRank isminde static class ekliyoruz.
GooglePageRank static class’ı üç tane static method’dan oluşuyor.
private static void Mix(ref uint a, ref uint b, ref uint c) { a -= b; a -= c; a ^= c >> 13; b -= c; b -= a; b ^= a << 8; c -= a; c -= b; c ^= b >> 13; a -= b; a -= c; a ^= c >> 12; b -= c; b -= a; b ^= a << 16; c -= a; c -= b; c ^= b >> 5; a -= b; a -= c; a ^= c >> 3; b -= c; b -= a; b ^= a << 10; c -= a; c -= b; c ^= b >> 15; }</pre>
private static string GoogleChecksum(string url) { uint GoogleMagic = 0xE6359A60; uint a, b; uint c = GoogleMagic; a = b = 0x9E3779B9; int k = 0; int length = url.Length; while (length >= 12) { a += (uint)(url[k + 0] + (url[k + 1] << 8) + (url[k + 2] << 16) + (url[k + 3] << 24)); b += (uint)(url[k + 4] + (url[k + 5] << 8) + (url[k + 6] << 16) + (url[k + 7] << 24)); c += (uint)(url[k + 8] + (url[k + 9] << 8) + (url[k + 10] << 16) + (url[k + 11] << 24)); Mix(ref a, ref b, ref c); k += 12; length -= 12; } c += (uint)url.Length; switch (length) { case 11: c += (uint)(url[k + 10] << 24); goto case 10; case 10: c += (uint)(url[k + 9] << 16); goto case 9; case 9: c += (uint)(url[k + 8] << 8); goto case 8; case 8: b += (uint)(url[k + 7] << 24); goto case 7; case 7: b += (uint)(url[k + 6] << 16); goto case 6; case 6: b += (uint)(url[k + 5] << 8); goto case 5; case 5: b += (uint)(url[k + 4]); goto case 4; case 4: a += (uint)(url[k + 3] << 24); goto case 3; case 3: a += (uint)(url[k + 2] << 16); goto case 2; case 2: a += (uint)(url[k + 1] << 8); goto case 1; case 1: a += (uint)(url[k + 0]); break; default: break; } Mix(ref a, ref b, ref c); return string.Format("6{0}", c); }
public static string PageRankHesapla(string adres) { string checkSum = GoogleChecksum("info:" + adres); string url = "http://toolbarqueries.google.com/search?client=navclient-auto&ch=" + checkSum + "&features=Rank&q=info:" + adres; try { WebRequest request = WebRequest.Create(url); WebResponse response = request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string data = reader.ReadToEnd(); reader.Close(); response.Close(); if (data.IndexOf(':') != -1) data = data.Substring(data.LastIndexOf(':') + 1); return data; } catch (Exception) { return "-1"; } } Şimdi yapmamız gereken, Butonun *Click* olayında, *GooglePageRank* static class'ının *PageRankHesapla* method'unu çağırmak ve dönen değeri Label'da göstermek. Uygulamanın çalışır halini bu adresten indirebilirsiniz.
Dün Emre (nam-ı diğer kara) arkadaşımla internette gezerken, bir youtube video’suna denk geldik. Emre’nin bilgisayarındaki hosts dosyasında güncel youtube ip adresleri olmadığı için videoyu izleyemedik.
Aklımıza, youtube domainine ait ip adreslerini otomatik olarak bulacak ve hosts dosyasını güncelleyecek bir uygulama yazmak geldi. Öğle yemeğine çıkmamıza 15 dakika olduğu için, bunu bir yarışa dönüştürmeye karar verdik.
İşte Yarışmanın Kuralları;
Sizinde 15 dakikanız var, code challenge‘ımıza katılmak ister misiniz?
Benim çözümümü görmek için
Ben öncelikle http://www.hcidata.info/host2ip.cgi adresindeki formu inceleyerek başladım;
WebRequest sınıfından bir örnek oluşturdum, sayfanın çıktısını GetResponse() methodu ile alarak WebResponse sınıfında bir nesnede sakladım. StreamReader nesnesini kullarak, sayfanın HTML çıktısını string tipinde bir değişkene atadım.
v{1-24}.lscache{1-8}.c.youtube.com adreslerinin ip adreslerini bulmak için içiçe iki paralel for döngüsü kurdum.
response değişkeninde oluşan HTML’i parse ederek, ip adresine ulaştım.
hosts dosyasında youtube.com adresli satırları bulmak ve güncellemek için .Net Regular Expression (Regex) classını kullandım.
Son olarak, bu kodları fonksiyon haline getirdim;
private void btnIPBul_Click(object sender, EventArgs e) { txtHosts.Clear(); StringBuilder sb = new StringBuilder(); sb.AppendLine(string.Format(“{0}\t{1}”, FindIP(“youtube.com”), “youtube.com”)); sb.AppendLine(string.Format(“{0}\t{1}”, FindIP(“www.youtube.com”), “www.youtube.com”)); sb.AppendLine(string.Format(“{0}\t{1}”, FindIP(“img.youtube.com”), “img.youtube.com”)); Parallel.For(1, 9, iLoop => { Parallel.For(1, 25, yLoop => { string url = string.Format(“v{0}.lscache{1}.c.youtube.com”, yLoop, iLoop); sb.AppendLine(string.Format(“{0}\t{1}”, FindIP(url), url)); }); });
txtHosts.Text = sb.ToString(); }
private string FindIP(string AddressToLookUp) { WebRequest r = WebRequest.Create(string.Format(“http://www.hcidata.info/host2ip.cgi?domainname={0}&findIP=Find IP Address&ipaddress=127.0.0.1”, AddressToLookUp)); WebResponse s = r.GetResponse();
StreamReader sr = new StreamReader(s.GetResponseStream(), Encoding.UTF8);
string response = sr.ReadToEnd();
sr.Close();
s.Close();
string ipAddress = response.Substring(response.IndexOf("IP Address : ") + 13, 16);
return ipAddress.Substring(0, ipAddress.IndexOf("\n")); }
private void btnHostsGuncelle_Click(object sender, EventArgs e) { if (txtHosts.Text == “”) btnIPBul.PerformClick();
Regex r = new Regex(@"^(.*youtube\.com)");
StringBuilder sb = new StringBuilder();
foreach (string line in File.ReadAllText(@"C:\Windows\System32\drivers\etc\hosts").Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
if (!r.IsMatch(line))
sb.AppendLine(line);
sb.AppendLine();
sb.AppendLine();
sb.AppendLine("# youtube.com IP'leri Buradan Başlıyor");
sb.Append(txtHosts.Text);
File.WriteAllText(@"C:\Windows\System32\drivers\etc\hosts", sb.ToString()); }
Uygulamanın kodlarını buradan indirebilirsiniz.
Daha önce yazdığım C#’ta anahtar kelimeyi değişken ismi olarak kullanma yazımda, aynı işin VB.NET’te nasıl yapılacağını yazmamıştım.
Değişken isminin, dilin anahtar kelimelerinden biri olmasına verbatim identifier deniyor.
MSDN’de C# dili için verbatim identifier nasıl tanımlanır makalesi mevcut, fakat VB.NET için nasıl yapılacağı dökümante edilmemiş.
Hala verbatim identifier tanımlamanın KÖTÜ bir fikir olduğunu düşünüyorum, fakat VB.NET’te verbatim identifier nasıl tanımlanır, merak edenler için;
Dim [String] As String = “” Dim [For] As Boolean = True Dim [While] As Integer = 6 Dim [False] As DateTime = DateTime.Now Dim [ReadOnly] As File
Sql Server’da veritabanında zaten varolan bir tabloya yeni bir alan eklemek istiyorsunuz. Yeni ekleyeceğiniz alanda, PersonelNo bilgisini saklayacaksınız.
PersonelNo bilgisi herzaman 5 karakterden oluşuyor. Dünya üzerinde çeşitli ülkelerde çalışan yüzlerce çalışanınız olduğu için, PersonelNo alanında saklayacağınız bilgiler genelde Unicode karakterlerden oluşuyor.
PersonelNo alanı için en uygun veritipi ne olmalı?
nchar veritipi sabit-uzunluklu unicode veri saklayabilir. Sorudaki ihtiyaçlar için, nchar(5) veritipini seçmek en mantıklısı olacaktır.
varchar veritipi değişken-uzunluklu metin bilgisi saklayabilir. Sorudaki ihtiyaç, sabit uzunluk (5) olduğu için, bu veritipini seçmek gereksizdir.
nvarchar veritipi değişken-uzunluklu unicode veri saklayabilir. Sorudaki ihtiyaç, sabit uzunluk (5) olduğu için, bu veritipini de seçmemeliyiz.
char veritipi unicode veri saklayamaz.
Senior Software Engineer, @Microsoft
Ada ve Ege'nin babası ;)
Makale Adedi: 484