- Mesajlar
- 1,737
Düzenli ifadeler bir metin içerisinde belirlenmiş kurallara ve desenlere uyan büyük veya küçük metin ve metin parçalarını sorgulamaya yarayan yapılardır. Düzenli ifadeleri aklınıza gelecek her alanda kullanabilirsiniz. Javascript kullanarak bir input kontrole e-posta adres türünün girilmesini zorlayabileceğimiz gibi robot yazarak belirtilen hedef sitelerdeki verilerin otomatik olarak sistemimize yüklemesini sağlamak gibi. Peki bu düzenli ifadeler nedir? Csharpnedir.com ve benzer sistemlerden derlediğim açıklamaları belirteyim akabinde de MEB’in bazı genel müdürlük sayfalarındaki duyuruları otomatik olarak indeksleyecek basit bir kod yazalım.
Regular Expression’larda Kullanılan Özel Karakterler ve Etkileri
Gelelim Uygulamamıza
Aynı yapıyı ben şu anda http://www.testsinavi.com da kullanıyorum. Bunun bir benzeri bir uygulamayı da http://www.videoege.com da filmleri veritabanıma eklemek için kullanıyorum. Film sitelerindeki filmleri buluyor, resimleri ayrı açıklamaları ayrı ve videolarını ayrı olarak sisteme ekliyor. Siz pleskten gidip Zamanlayıcı (Crontab) oluşturarak böyle bir uygulamayı otomatikleştirebilir ve sisteminize otomatik olarak haberleri girebilirsiniz. Haber scriptiniz kendi kendine haber ekler.
Arkadaşlar bu ileri düzey bir uygulama olduğu için bazı temel methodlara ve veritabanı kayıt işlemlerine deyinmedim bunları zaten biliyor olmanız gerekiyor. Kolay gelsin arkadaşlar
Regular Expression’larda Kullanılan Özel Karakterler ve Etkileri
Regular expression desenleri tanımlamada kullanılan özel karakterleri örnekleri ile anlatırsak sanırım regular expressionlar daha tanıdık ve kolay gelebilir.
1.) “.” Karakteri
Tek bir karakteri temsil eder(yeni satır karakteri hariç).
“CSharp.edir” şeklindeki bir desen CSharpnedir, CSharpNedir, CSharpSedir, CSharp3edir gibi stringleri döndürebilir.
2.) “[]” Karakterleri
Bir arrayi yada aralığı temsil eder.
“CSharp[SNY]edir” deseni, CSharpSedir, CSharpNedir ve CSharpYedir stringlerini döndürür.
“CSharp[a-z]edir” şeklindeki kullanım aralık belirtmeye yarar.
“CSharp[0-9]edir” şeklindeki kılanlım ise sayısal aralık belirtmeye yarar.
3.) “?” Karakteri
Kendinden önceki karakterin stringte olması yada olmamasını sağlar.
“CSharpn?edir” deseni CSharpedir yada CSharpnedir döndürür.
4.) “\” Karakteri
Kendinden sonraki özel karakterin stringe dahil edilmesini sağlar.
“CSharpnedir\?” deseni CSharpnedir? Stringini döndürür. (Eğer “\” karakterini kullanmamış olsaydık CSharpnedi yada CSharpnedir dönerdi.)
5.) “*” Karakteri
Kendinden önceki karakterin yada stringin hiç olmaması yada istediği sayıda olmasını sağlar.
“CSharpnedir*” deseni, CSharpnedi, CSharpnedir, CSharpnedirr, CSharpnedirrr, ... döndürür. “CSharp(nedir)*” deseni ise CSharp, CSharpnedir, CSharpnedirnedir, ... döndürür.
6.) “{}” Karakterleri
Kendinden önce gelen karakterin belirtilen sayıda tekrar etmesini sağlar.
“C{4}Sharpnedir” deseni, CCCCSharpnedir stringini döndürür.
7.) “^” Karakteri
Satır başını ifade eder.
“^CSharpnedir” deseni, satır başında “CSharpnedir” stringi varsa bunu döndürür.
8.) “$” Karakteri
Satır sonunu ifade eder.
“CSharpnedir$” deseni, satır sonunda “CSharpnedir” stringi varsa bunu döndürür.
Gelelim Uygulamamıza
Kod:
using System.Text.RegularExpressions;
using System.IO;
using System.Net;
using System.Text;
protected void Page_Load(object sender, EventArgs e)
{
}
/*
* linkBolumleri adında 2 özellikli bir yapı tanımlıyoruz. Neden class yerine yapı tanımladık.
* Yapılar, sınıflar ile büyük benzerleklik gösterirler. Sınıf gibi tanımlanırlar.
* Hatta sınıflar gibi, özellikler,metodlar,veriler, yapıcılar vb... içerebilirler.
* Buna karşın sınıflar ile yapılar arasında çok önemli farklılıklar vardır.
*
* Herşeyden önce en önemli fark, yapıların değer türü olması ve sınıfların referans türü olmasıdır.
* Sınıflar referans türünden oldukları için, bellekte tutuluş biçimleri değer türlerine göre daha farklıdır.
* Referans tiplerinin sahip olduğu veriler belleğin öbek(heap) adı verilen tarafında tutulurken,
* referansın adı stack(yığın) da tutulur ve öbekteki verilerin bulunduğu adresi işaret eder.
* Ancak değer türleri belleğin stack denilen kısmında tutulurlar.
*
* Şimdi bunun bizim için ne önemi var?
* Küçük boyutlarda veriler ile çalışırken bu verileri sınıflar içerisinde kullandığımızda
* bu kezde gereksiz yere bellek kullanıldığı öbek şişer ve performans düşer.
* Bu konudaki uzman görüş 16 byte'tan küçük veriler için yapıların kullanılması,
* 16 byte'tan büyük veriler için ise sınıfların kullanılmasıdır.
*/
private struct linkBolumleri
{
public string[] _basliklar;
public string[] _url;
}
/* getPageInformation() fonksiyonu bize hedef sayfanın aşağıda strUrl olarak nitelendiriliyor;
* Html kodlarını getirir. Bunun için WebRequest ve WebResponse methodlarından yararlanacağız.
* Bunların burada nasıl kullanıdığına deyinmeyeceğim.
* StreamReader sr = new StreamReader(webCevap.GetResponseStream(), Encoding.GetEncoding("ISO-8859-9"));
* ile tüm kodları sr StreamReader nesnesine aktaradık. sr.ReadToEnd() tüm sayfa kodlarını
* string ifadeye çevirdi.
*/
private string getPageInformation()
{
string icerik = "";
string strUrl = "";
strUrl = "http://www.meb.gov.tr/duyurular/index.asp?ID=4";
WebResponse webCevap;
WebRequest webTalep = WebRequest.Create(strUrl);
webCevap = webTalep.GetResponse();
StreamReader sr = new StreamReader(webCevap.GetResponseStream(), Encoding.GetEncoding("ISO-8859-9"));
icerik = sr.ReadToEnd();
sr.Close();
webCevap.Close();
return icerik;
}
//Tüm duyuru kısımlarının tutulduğu bölüm
/* İşte dananın kuyruğunun koptuğu kısım
* string _pattern = "<li class=\"im[3|6]\">((.|\n)*)?</li>"; ifadesi ne demek?
* hedef urlden talep ettimiz html kodlarına bakıyoruz. ben burada <li class="im3">..</li> veya
* <li class="im6">..</li> lı hedef ifadeleri hedef aldım bunu _patter adında bir metne bu deseni
* atadık. bu bizim metin sorguları için kullanacağımız desenimiz.
* Regex _regex = new Regex(_pattern); ile _regex adında bir düzenli ifade tanımladık.
*
* Match bulunan = _regex.Match(this.getPageInformation()); Match türünde bulunan adlı nesnemizi
* tanımladık. Matches türü kullansaydık sonuçları dizi olarak alacaktık.
*
* string _tmpIcerik = "<ul>";
_tmpIcerik = bulunan.Value.Replace(_tmpIcerik, "");
_tmpIcerik = _tmpIcerik.Replace("</ul>", "");
*
* bu kod ise elde ettiğimiz veride yaptığımız temizlik işlemi.
*/
private linkBolumleri fnklinkBolumleri()
{
string _pattern = "<li class=\"im[3|6]\">((.|\n)*)?</li>";
Regex _regex = new Regex(_pattern);
Match bulunan = _regex.Match(this.getPageInformation());
string _tmpIcerik = "<ul>";
_tmpIcerik = bulunan.Value.Replace(_tmpIcerik, "");
_tmpIcerik = _tmpIcerik.Replace("</ul>", "");
return this.liMatch(_tmpIcerik);
}
/* Burada benzer bir işlemide linkleri elde etmek için kullandık.
* MatchCollection _matches = _regex.Matches(metin); ile sonuçları
* dizi olarak aldık.
*
*/
private linkBolumleri liMatch(string metin)
{
linkBolumleri li = new linkBolumleri();
string _pattern = "<a(.|\n)*?>(.*?)\n*</a>";
Regex _regex = new Regex(_pattern);
MatchCollection _matches = _regex.Matches(metin);
int i = 0;
li._basliklar = new string[_matches.Count];
li._url = new string[_matches.Count];
foreach (Match bulunan in _matches)
{
li._basliklar[i] = this.toBaslik(bulunan.Value, li).
Replace("</a>", "").Replace(">", "");
li._url[i] = this.toUrl(bulunan.Value, li).
Replace("\"", "");
if ((li._url[i].IndexOf("/", 0) == 0))
li._url[i] = "http://www.meb.gov.tr" + li._url[i];
if(li._url[i].IndexOf("http", 0) == -1)
li._url[i] = "http://www.meb.gov.tr/" + li._url[i];
i++;
}
return li;
}
// İlgili haberlerin urllerini elde ediyoruz.
private string toUrl(string metin, linkBolumleri li)
{
string _pattern = "\"(.*?)\n*\"";
Regex _regex = new Regex(_pattern);
Match _match = _regex.Match(metin);
return _match.Value;
}
// İlgili haberlerin başlıklarını elde ediyoruz.
private string toBaslik(string metin, linkBolumleri li)
{
string _pattern = ">(.*?)\n*</a>";
Regex _regex = new Regex(_pattern);
Match _match = _regex.Match(metin);
return _match.Value;
}
// Burada da elde ettiğimi sonuçları veritbanına aktarıtoruz.
/*
* databaseProcess.KayitIslemi_MebBilgilendirme(b._basliklar[i], lb._url[i]) > 0) bu method
* aklınızı karşıtırmasın bu benim kendi veritabanıma eklemek için kullandığım bir class
* siz b._basliklar[i] ve lb._url[i] ile başlıklar ve urlleri veritabanınıza ekleyebilirsiniz.
*/
protected void btnAktar_Click(object sender, EventArgs e)
{
linkBolumleri lb = this.fnklinkBolumleri();
int linkSayisi = lb._basliklar.Length;
int _basariliKayit = 0;
int _basarisizKayit = 0;
for (int i = linkSayisi - 1; i >= 0; i--)
{
if (databaseProcess.KayitIslemi_MebBilgilendirme(
lb._basliklar[i], lb._url[i]) > 0)
_basariliKayit++;
else
_basarisizKayit++;
}
lbDurum.Text = "Dikkat!: " + _basariliKayit.ToString() + " adet başarılı kayıt." + "\n";
lbDurum.Text += _basarisizKayit.ToString() + " adet başarısız kayıt vardır.";
}
Aynı yapıyı ben şu anda http://www.testsinavi.com da kullanıyorum. Bunun bir benzeri bir uygulamayı da http://www.videoege.com da filmleri veritabanıma eklemek için kullanıyorum. Film sitelerindeki filmleri buluyor, resimleri ayrı açıklamaları ayrı ve videolarını ayrı olarak sisteme ekliyor. Siz pleskten gidip Zamanlayıcı (Crontab) oluşturarak böyle bir uygulamayı otomatikleştirebilir ve sisteminize otomatik olarak haberleri girebilirsiniz. Haber scriptiniz kendi kendine haber ekler.
Arkadaşlar bu ileri düzey bir uygulama olduğu için bazı temel methodlara ve veritabanı kayıt işlemlerine deyinmedim bunları zaten biliyor olmanız gerekiyor. Kolay gelsin arkadaşlar