Selenium ile Nöbetçi Eczane Botu Yapımı

İstanbullu

Yeni Üye
Son günlerde adını çok sık duyduğumuz C# Selenium hakkında sizlere kısa bilgiler vererek daha sonra ufak bir projeyle C# Selenium kavramını anlatmaya çalışacağım. Bu yazımıza başlamadan önce yapacağım projeyi söylemek istiyorum.
C# Selenium kullanarak sizlerle Nöbetçi Eczane uygulaması yapacağız. Bu sayede kendi yapmış olduğunuz C# Form Uygulaması üzerinden Türkiye’deki 81 ilin il ve ilçelerindeki nöbetçi eczaneleri görebileceğiz.
Uygulamamızda kullanacağımız kütüphaneleri NuGet Paket Konsolundan yada NuGet araçlarından yükleyebiliriz. Ben sizlere iki yolunuda göstereceğim. Kütüphanelere geçmeden önce projemizde kullanacağımız araçlarımızı form üzerine yerleştirelim.
C# Form uygulamamızda 1 adet PictureBox(opsiyonel), 3 adet Label, 2 adet ComboBox, 1 adet ListView kullanacağız ekran görüntümüz aşağıdaki gibi olacak.
C# Selenium ile Nöbetçi Eczane Botu 1
Tasarımımızı yaptığımıza göre artık kütüphanelerimizi uygulamamıza dahil edebiliriz. Yukarıda 2 yolunu da göstereceğimi söylemiştim.

1.NuGet Paket Yöneticisi Konsolu
Araçlar -> NuGet Paket Yöneticisi -> Paket Yöneticisi Konsoluna tıkladıktan sonra aşağıdaki kodu yazarak otomatik olarak kütüphaneyi uygulamamıza dahil edebiliriz.
Install-Package Selenium.WebDriver -Version 3.141.0

2.NuGet Paketlerini Yönet
Çözüm Gezgini -> NuGet Paketlerini Yönet -> Selenium yazarak karşımıza gelen 3 adet kütüphaneyi uygulamamıza dahil ediyoruz. Bunlar ;
1)Selenium.WebDriver
2)Selenium.Support
3)Selenium.Chrome.Driver
using OpenQA.Selenium.Chrome;
using System.Data.SqlClient;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using System.Globalization;
Kütüphanelerimizi uygulamamıza dahil ettik sıra geldi bu kütüphanelerimizi kullanmaya. Selenium da normal WebBrowser’dan farklı olarak bir Windows cmd uygulamamızı çalıştırdıktan sonra ekranda beliriyor. Biz bu siyah ekranı ilk olarak arka plana atalım bunun için aşağıdaki kodları yazıyoruz.
Kod:
public IWebDriver driver;
public Form1()
{
CheckForIllegalCrossThreadCalls = false;
ChromeDriverService service=ChromeDriverService.CreateDefaultService();
service.HideCommandPromptWindow = true;
driver = new ChromeDriver(service);
InitializeComponent();
}
Burada yaptığımız işlem açılan Chrome sayfası ve cmd ekranını uygulamamızın arka planına atmak. Ben araştırdım fakat onlar kapalıyken veriyi bir türlü içeri çekemedim. Eğer siz çözümü bulduysanız bizimle de paylaşabilirsiniz.
Şimdi sıra geldi ComboBox nesnelerimizi doldurmaya 81 ilin ve illerin ilçelerinin hepsini ben internetten bir sql kaynağı olarak buldum ve kendi yerel sunucuma kayıt ettim. Sizde SQL Server yoksa elinizle 3-4 kayıt il ve ilçe atıp test edebilirsiniz. İndirip SQL Serverına kayıt etmek isteyen arkadaşlar buradan dosyayı indirebilir.
Sıra geldi SQL Bağlantı kodlarımıza bağlantı kodlarımız aşağıda gibi olacak.
Kod:
SqlConnection con;
SqlDataAdapter da;
SqlDataReader dr;
SqlCommand cmd;
    void illerTablosu()
    {
        con=new SqlConnection(@"server=.\SQLExpress; Initial Catalog =illerIlceler;Integrated Security=SSPI");
        cmd = new SqlCommand();
        con.Open();
        cmd.Connection = con;
        cmd.CommandText = "SELECT * FROM iller";
        dr = cmd.ExecuteReader();
        while (dr.Read())
        {
            comboBox1.Items.Add(dr["sehir"]);
        }
        con.Close();
    }
SQL Veri tabanımızdan şehirleri çekip ComboBox nesnemize aktardık. Uygulamamız açıldığında bu şehirlerin gelmesi için bu fonksiyonumuzu çağırıyoruz.
private void Form1_Load(object sender, EventArgs e)
{
illerTablosu();
}
Sıra geldi seçtiğimiz İL göre İLÇELERİMİZİN gelmesine bunun için ComboBox nesnemizin SelectedIndexChanged özelliğini kullanacağız bu sayede seçtiğimiz satıra göre işlem yapıp bize o İL’in İLÇELERİNİ getirecek.
Kod:
private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
         {      
 con = new SqlConnection(@"server =.\SQLExpress; Initial Catalog = illerIlceler; Integrated Security = SSPI");
        cmd = new SqlCommand();
        con.Open();
        cmd.Connection = con;
        cmd.CommandText = "SELECT * FROM ilceler where sehir='" + (comboBox1.SelectedIndex + 1).ToString() + "'";
        dr = cmd.ExecuteReader();
        comboBox2.Items.Clear();

        while (dr.Read())
        {
            comboBox2.Items.Add(dr["ilce"]);
        }
        con.Close();
    }
Sorgumuzda + 1 koymamızın nedeni ComboBox değerlerimizin indisinin sıfırdan(0) başlıyor olması. Böylece 10.satırı seçtiğimizde bize “Balıkesir” İL’ini döndürmesi. Örnek olarak “Balıkesir” seçildiğinde bize “Balıkesir” ilçeleri karşımıza gelecek.
Aşağıda vermiş olduğum kod biraz karışık olduğu için tek seferde paylaşıp altında satır satır açıklamalarını ve yazının sonunda uygulamanın düzgün bir şekilde çıktısını vereceğim.

Kod:
private void ComboBox2_SelectedIndexChanged(object sender, EventArgs e)

         {label3.Text = "https://ecza.io/" + comboBox1.SelectedItem + "-" + comboBox2.SelectedItem + "-nobetci-eczane";

label3.Text = label3.Text.ToLower(new CultureInfo("en-US", false));

             driver.Navigate().GoToUrl(label3.Text);             

             int nobetciSayisi = Convert.ToInt32(driver.FindElement(By.XPath("/ html / body / div[3] / div / div / div[1] / div[2] / p[1] / strong")).Text.Trim().ToString());       

int[] dongu = { 3, 4, 6, 7, 8 };

        int elemanSayisi = dongu.Count();





        for (int i = 0; i <= nobetciSayisi - 1; i++)

        {

            string ecz1 = driver.FindElement(By.XPath("/html/body/div[3]/div/div/div[1]/div[" + dongu[i] + "]/div[3]/div/div/h6")).Text.Trim().ToString();

            string ecz1Adress = driver.FindElement(By.XPath("/html/body/div[3]/div/div/div[1]/div[" + dongu[i] + "]/div[3]/div/div/p[1]")).Text.Trim().ToString();

            string ecz1Tel = driver.FindElement(By.XPath("/html/body/div[3]/div/div/div[1]/div[" + dongu[i] + "]/div[3]/div/div/p[2]/a")).Text.Trim().ToString();



            ListViewItem item = new ListViewItem(ecz1);

            item.SubItems.Add(ecz1Adress);

            item.SubItems.Add(ecz1Tel);

            listView1.Items.Add(item);       

        }

        driver.Close();

    }
Selenium kütüphanemiz biz ilçeyi seçtikten sonra devreye giriyor. Ben site verilerini ecza.io sitesinden çektim. Siz başka sayfalardan verileri çekerken bilgiler değişebilir. Vermiş olduğum sitenin urlsine baktığımda /il-ilce-nobetci-eczane uzantısının olduğunu farkettim ve Combobox nesnelerimden seçilen il ve ilçe isimlerini alarak Label3 nesneme aktardım. Siz bunu veri göndererekte yapabilirsiniz. Ben yukarıda il seçeneğini gönderip butona tıklatma yaptığım için burada farklı bir örnek vermek istedim. Label3 nesnemi küçük harflere çevirerek ingilizce karakterle yazılmasını söyledim ve gelen veriler (Örnek : /balikesir-bandirma) oldu. Sonuna nobetci-eczane yazarak linkimi oluşturdum ve istediğim sayfaya eriştim. Daha sonra sitede verilen bugünkü nöbetçi eczane sayısını çekerek for döngüsüyle o kadar kez dönmesini sağladım. Bu sayede bütün nöbetçi eczaneleri çektim.

C# Selenium ile Nöbetçi Eczane Botu 2

Şimdi en önemli yere geldik sizin burada dikkat etmeniz gereken ve ilk başlarda karıştıracağınız çıkmaza düşeceğiniz yer burası. Eğer bir siteden veri çekmeye kalktığınızda id veya name alanları yoksa size Selenium çok güzel bir alan sağlıyor bu da XPath yolu. XPath yolunu nasıl buluruz aşağıda resimde gösterdim. Selenium kütüphanemizin FindElement özelliği ile XPath aratarak nesnelerimizi buluyoruz.

Div içine döngü yazdığımı göreceksiniz bunlar o il ve ilçenin bütün nöbetçi eczanelerini gezip arttırarak diğer nöbetçi eczanenin alınmasını sağlıyor. Daha sonra bunları ListView nesneme aktarıyorum ve kayıt işlemlerini gerçekleştiriyorum.

Ve projemiz bu sayede bitmiş oldu. İl ve ilçesini seçtiğimiz nesnelerimiz bize bizim ayarlamış olduğumuz web sayfasın giderek gerekli alanları çekip ListView nesnemize kayıt ediyor. Siz farklı sayfalardan veri çekerek başka projeler gerçekleştirebilirsiniz. İnternette Selenium ile ilgili kaynak çok az olduğu için sizlerle böyle bir yazı paylaşma gereksinimi duydum umarım yararlı olmuştur.