Bot yazacaklar için yol haritası 2 [Anlatım] ÖRNEK BOT YAPIMI

19 May 2020
238
84
1. bölüm
2. bölüm (şuan buradasınız)
3. bölüm

ANALİZ
evet, aslında post tutmuştum ama, şimdi sanıyorum ki 3-4 kez flood yapmam gerekecek anlatımı bitirmek için, bu yüzden konunun devamı niteliğinde bir konu açtım. Botumuz pdf kitapları listeleyecek, açacak ve okuyacak. bunun için öncelikle botun etkileşimde bulunacağı siteyi inceliyoruz. PDF Drive - Ücretsiz kitaplar arayın ve indirin. botu yazacağımız site bu. botun ilk istekte bulunacağı kısım site içi arama olduğu için test amaçlı bir arama gerçekleştiriyorum.
4gwy9tv.jpg

get methodu kullanarak yapılan istekleri parametre olarak url de görebildiğimiz için, öncelikle bu parametre değerlerini analiz ile başlayalım.
q= parametresi aranan metin değerini alıyor
extract match = q parametresinden kalıtım alıyor ve değeri tırnak içerisine alarak kesin sonuçlar ile eşleştirmeye çalışıyor.
pagecount= kitap sayfası anlamına geliyor, tüm sonuçlara baktığımız için boş, örneğin 1-24 değerini tanımladığımız da 1 ila 24 sayfalık kitapları listeliyor.
pubyear= kitabın yayınlandığı veya siteye yüklendiği tarih
searchin= kitabın yazıldığı veya çevrildiği dil

evet şimdi bu parametreleri incelediğimize göre aşağı yukarı aramaya dair isteklerimizin nasıl gerçekleştiği hakkında fikir sahibi olduk demektir. şimdi gelelim sonuçlardan herhangi birinden değer almaya. bu yüzden arama sonuçlarında listelenen kitaplardan birine tıklıyorum ve bu sayfa yapısını da inceliyorum.

4f7ev0a.jpg

sayfaya bağlandığımda görüyorum ki urlde bir id değeri mevcut ve başına getirilen ifade ile farklı anlamlandırılan sayfalaa yönlendiriyor. örneğin e{ID} bu sayfayı açarken d{ID} bu kitabı indirme isteği yapacak olan sayfaya yönlendiriyor. ayrıca kitabı önizleme yapabilmek için burada geçerli bir oturumum olması gerektiğini data-preview içerisindeki parametrelerden anlıyorum. bu demek oluyor ki botumuzda çerezler için bir dosya oluşturmamız gerekecek ki, bizi 404 veya çeşitli hata sayfalarına yönlendirmesin. şimdi önizlemeye tıklayarak nasıl bir yanıt alacağımıza kullanıcı gözüyle bir bakalım.

dz80s44.jpg

bir iframe ile karşılaştık. çerçeve kaynağını görüntüle dediğimizde;
view-source:dl2.php
böyle bir url ile karşılaşıyoruz. bu ne demek oluyor? bu şu demek oluyor, bu site pdf kitaplarını 3. bir sunucuda barındırıyor ve önizleme sağlaması için de google'ın dosya sistemini kullanıyoruz. biz bu veriyi aldıktan sonra, diğer sunucuya ulaşmalıyız. yani ?url= parametresinin değerinde bulunun ikincil url'in decode edilmiş haline. decode edilmiş mi? evet decode. url'ler yani linkler, bir internet sitesinin adresinde parametre değeri olarak kullanılmak üzere url formatında şifrelenir. bakalım bu urle gidince bizi ne bekliyor.
url'in decode hali : https://preview.pdcdn.xyz/dl2.php?i...df&n=Hızlı+prototip+yapımı&embedded=true&1078
adrese gidince herhangi bir sayfa açılmıyor ve doğrudan dosya indiriliyor. ancak bu url'de de gördüğünüz üzere bir oturum benzeri parametreler söz konusu. evet analizimiz buraya kadardı. artık kodlama aşamasına geçebiliriz, yeterince bilgi edindik hedefimiz için.

Kullanılacak Eklentiler
PDF Parser: GitHub - smalot/pdfparser: PdfParser, a standalone PHP library, provides various tools to extract data from a PDF file. pdf dosyasını string değerlere yani metne dönüştürür (githubda'ki hali verimsiz ve hatalı olduğu için yeniden düzenledim ama pdf metne dönüştürmemi sağlayan asıl kaynak bu)
ResponsiveVoice: ResponsiveVoice Setup Guide - ResponsiveVoice.JS Text to Speech metin değerlerini sese dönüştüren bir api. Javascript kullanılarak yazılmıştır.
Bu çalışmada kullanacağım eklentiler bu kadar.


KODLAMA
kod yazmaya başlamadan önce, yapılacak işin üzerinde yeterince düşünülmesi gerekir. nereden başlanmalı, nasıl devam edilmeli ve nasıl mantık kurulmalı, bu sistem nasıl daha verimli çalışır, nasıl daha az kodla daha çok iş yaparım gibi. ben şöyle düşündüm, yapacağım istekler ve bu isteklere verilen cevaplar için kullanıma açık bir proje oluşturabilirim. bu yüzden, botu yazmaya başlamadan önce bu sitede söz sahibi olmak için bir api yazmaya karar verdim. sonuçta uzak bir sunucu ve veritabanında söz sahibi değilim. söz sahibi olsam bot yazmama gerek kalmayacaktı. bende bu sorunu ortadan kaldırmak için, içeriği okuma ve çalıştırma adına alabileceğim yetkileri zorlamaya karar verdim ve pdf hunter adında bir class oluşturdum. önce bu yapıyı bir inceleyelim;

PHP:
 class PDFHunter{
     public function __construct(){
         $_GET ? (isset($_GET["q"]) ? $this->KitaplariListele() : die($this->Hatalar(3)) ) : die($this->Hatalar(4));
     }
     public function Parametreler(){
         extract($_GET);
         $ara = htmlspecialchars($q);
         if(strlen($ara) > 3){
             $dosya = "../Onbellek/query/$ara.txt";
             $parametreler = json_encode(["ara" => urlencode($ara), "dosya" => $dosya], JSON_UNESCAPED_UNICODE);
             return json_decode($parametreler);
         }else{
             die(json_encode(["Durum" => "false", "hata" => "en az 4 karakter içeren bir arama yapın"],JSON_UNESCAPED_UNICODE));
         }
      
     }
     public function Arama(){
         $dosya = $this->Parametreler()->dosya;
         if(file_exists($dosya)){
             $sonuc = file_get_contents($dosya);
         }else{
             $url = 'https://www.pdfdrive2.com/search?q="'.$this->Parametreler()->ara.'"&pagecount=&pubyear=&searchin=tr&em=&more=true';
             $curl = curl_init($url);
             curl_setopt($curl, CURLOPT_URL, $url);
             curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
             curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
             curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
             $resp = curl_exec($curl);
             curl_close($curl);
             file_put_contents($dosya, $resp);
             $sonuc = file_get_contents($dosya);
         }
         return !empty($sonuc) ? $sonuc : die($this->Hatalar(1));
     }
     public function SonucSayisi(){
        $resp = $this->Arama();
         preg_match('@<div id="result-found">(.*?)</div>@si', $resp, $sonuc); // bulunan sonuçların toplam sayısı
         preg_match('@<strong>(.*?)</strong>@si', $sonuc[0], $sonucsayisi); // bulunan sonuçların toplam sayısının metin değeri
         $ReturnToplamSonuc = str_replace(",", "", $sonucsayisi[1]);
         $Istatistikler = $sonucsayisi[1] > 0 ?
             (preg_match_all('@<div class="file-right">(.*?)</div>@si', $resp, $sonuclar) ?
              json_encode([
                  "toplam" => $ReturnToplamSonuc,
                  "gosterilen" => count($sonuclar[0]),
                  "sayfalar" => ceil($ReturnToplamSonuc / count($sonuclar[0]))
              ], JSON_UNESCAPED_UNICODE) : false
             ) : die($this->Hatalar(2,$this->Parametreler()->ara));
         return json_decode($Istatistikler);
     }
     public function RawResults(){
         $resp = $this->Arama();
         preg_match_all('@<div class="file-right">(.*?)</div>@si', $resp, $sonuclar);
         preg_match_all('@<img class="img-zoom file-img" src="(.*?)">@si', $resp, $resimler);
         return json_decode(json_encode([
             "sonuclar" => $sonuclar,
             "resimler" => $resimler
         ], JSON_UNESCAPED_UNICODE));
     }
     public function IdBul($value){
         $ids = explode('-', $value);
         $idsi = count($ids);
         $id = str_replace('.html', '', $ids[$idsi-1]);
         return $id;
     }
     public function Kitaplar($value){
         $sonuclar = $this->RawResults()->sonuclar;
         $resimler = $this->RawResults()->resimler;
         $ReturnToplamSonuc = $this->SonucSayisi()->toplam;
         //ikinci dizeyi değiştir
         preg_match_all('@src="(.*?)"@si', $resimler[0][$value], $resim);
         preg_match_all('@<span class="fi-pagecount ">(.*?)</span>@si', $sonuclar[0][$value], $sayfa);
         preg_match_all('@<span class="fi-size hidemobile">(.*?)</span>@si', $sonuclar[0][$value], $boyut);
         preg_match_all('@<span class="fi-hit">(.*?)</span>@si', $sonuclar[0][$value], $okunma);
         preg_match_all('@<span class="fi-lang">(.*?)</span>@si', $sonuclar[0][$value], $dil);
         preg_match_all('@<a href="(.*?)"@si', $sonuclar[0][$value], $baglanti);
         preg_match_all('@<h2>(.*?)</h2>@si', $sonuclar[0][$value], $adveyazar);
         $adiyazari = explode(" - ", $adveyazar[1][0]); // bu değer bir üstteki preg_match'den oluştuğu için değiştirilmez
         return json_encode([
             "Adi" => strip_tags($adiyazari[0]),
             "Yazari" => !empty($adiyazari[1]) ? strip_tags($adiyazari[1]) : 'Belirtilmemiş',
             "Sayfasi" => !empty($sayfa[1][0]) ? str_replace(" Sayfa", "", $sayfa[1][0]) : "boş",
             "Boyutu" => $boyut[1][0],
             "Indirilme" => str_replace(array(",", " İndirme"), array("", ""), $okunma[1][0]),
             "Dili" =>  $dil[1][0],
             "Baglantisi" => $baglanti[1][0],
             "Kapagi" => $resim[1][0],
             "Id" => str_replace('e', '', $this->IdBul($baglanti[1][0]))
         ], JSON_UNESCAPED_UNICODE);
     }
     public function KitaplariListele(){
         $Tekrarla = $this->SonucSayisi()->gosterilen;
         for ($x = 0; $x < $Tekrarla; $x++) {$sonuc[] = json_decode($this->Kitaplar($x), true);}
         //$sonuc[] = json_decode($this->Kitaplar(0), true);
         $donustur = ["Durum" => "true", "ToplamSonuc" => $this->SonucSayisi()->toplam, "GosterilenSonuc" => $this->SonucSayisi()->gosterilen, "Kitaplar" => $sonuc];
         header('Content-Type: application/json; charset=utf-8');
         echo json_encode($donustur,JSON_UNESCAPED_UNICODE);
     }
     public function Hatalar($value, $arama=''){
         $value = $value == 1 ? ["Durum" => "false", "hata" => "curl bağlanamadı lütfen tekrar deneyin"] :
         ($value == 2 ? ["Durum" => "false", "hata" => urldecode($arama)." arama için sonuç bulunamadı"] :
          ($value == 3 ? ["Durum" => "false", "hata" => "sorgu için sadece q parametresini kullan"] :
           ["Durum" => "false", "hata" => "parametre belirtilmemiş"])
         );
         return json_encode($value, JSON_UNESCAPED_UNICODE);
     }
 }

__construct yapıcı metot olarak geçer ve bir sınıf çağrıldığında çalıştırılacak ilk kısımdır. sınıf içerisinde bulunan metotlar genelde tek başına anlam ifade etmezler. bu yüzden sınıf içerisinde yer alan metotların sıralamasına göre bu yapıyı sizlere anlatmaya kalkarsam, sonundan bir parça, başından bir parça, ortasından bir parça anlatmış olurum. bu yüzden size yapının nasıl çalıştığını bildiğim için, aşama aşama ve bu kronolojiye göre anlatım yapacağım.
PHP:
     public function Parametreler(){
         extract($_GET);
         $ara = htmlspecialchars($q);
         if(strlen($ara) > 3){
             $dosya = "../Onbellek/query/$ara.txt";
             $parametreler = json_encode(["ara" => urlencode($ara), "dosya" => $dosya], JSON_UNESCAPED_UNICODE);
             return json_decode($parametreler);
         }else{
             die(json_encode(["Durum" => "false", "hata" => "en az 4 karakter içeren bir arama yapın"],JSON_UNESCAPED_UNICODE));
         }
      
     }
parametreler metotunda basit, sade bir işlem yürüyor. url'den aldığımız get değerini çıkartarak, html karakterler veya script dilinde bir ifade varsa bunları temizledikten sonra, aramayla aynı adda bir dosya yolu ve aranan metnin değeriyle ilgili, bu metottan sonra çalışacak olan metotlara yardımcı olması için değişkenler oluşturuyoruz. eğer aranan metnin karakter sayısı 3 den büyük değilse, bir uyarı vererek komutların çalıştırılmasını durduruyoruz.

PHP:
     public function Arama(){
         $dosya = $this->Parametreler()->dosya;
         if(file_exists($dosya)){
             $sonuc = file_get_contents($dosya);
         }else{
             $url = 'https://www.pdfdrive2.com/search?q="'.$this->Parametreler()->ara.'"&pagecount=&pubyear=&searchin=tr&em=&more=true';
             $curl = curl_init($url);
             curl_setopt($curl, CURLOPT_URL, $url);
             curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
             curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
             curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
             $resp = curl_exec($curl);
             curl_close($curl);
             file_put_contents($dosya, $resp);
             $sonuc = file_get_contents($dosya);
         }
         return !empty($sonuc) ? $sonuc : die($this->Hatalar(1));
     }

Arama metotuna baktığımız zaman, bir curl isteği görüyoruz ve bu istek, konunun başında analiz kısmında anlattığım search sayfasını baz alıyor. oradaki parametreler içerisinden sadece arama değerini değişken değer olarak aldım, gerisi sabit değerler. ancak metotun başında gerçekleşecek olayda bir dosya kontrolü yapıldığını görüyoruz. neden bir dosya kontrolüne ihtiyaç var? curl çok kararlı ve verimli bir yapıya sahip değil. böyle olsa bile aynı anda gerçekleştireceğiniz ve tekrar tekrar işleme tabi tutmanız gereken bir çok şey söz konusu olacak. bu da yazdığınız kodun verimliliğini düşürecek, hatta çalışmasına engel olacaktır. dolayısıyla bir önbellekleme yapılmasına ihtiyaç vardır.

Örneğin bu pdf kitap sitesine bağlandınız ve "Turk Hack Team" diye bir kitap arattınız. kod çalıştı, çalıştı, çalıştı, çalıştı. çalıştı, çalıştı, çok çok uzun süre sonra yanıt verdi veya yanıt vermedi. Durum böyle olursa yazdığınız koddan hayır gelmez. Ama şöyle yaparsak, a kişisi bir arama gerçekleştirdiğinde, diğer işlemler çalıştırılmadan sadece bu sorgu çalışırsa ve daha sonrasında alınan yanıt bir dosyaya yazılırsa ve ondan sonra gelecek işlemler bu dosyaya yazılan değerler baz alınarak yapılırsa, işte o zaman çok daha hızlı çalışacaktır. ve üstelik bu dosya sunucuda önbelleğe alındığı için, başka bir kişi tarafından aynı arama yapıldığında aynı anda eş zamanlı olarak sonuç kişinin önüne getirelecektir. işte bu yüzden metotun başında dedik ki;

PHP:
$dosya = $this->Parametreler()->dosya
yani bu şu demek, benim dosyamın adı yapılan aramanın adıyla aynı olsun. ardından
PHP:
         if(file_exists($dosya)){

             $sonuc = file_get_contents($dosya);

         }else{
             //curl komutları
         }
burada ise if else kullanarak eğer böyle bir dosya varsa sonuç olarak dosya içeriğini göster, eğer böyle bir dosya yoksa curl ile siteye bağlan ve aldığın sonuçları dosayaya kaydederek yine dosyadan göster diyoruz.

metotun sonunda ise kısa bir if else yapısı kurdum, kısa kullanımına aşina olmayanlar için hemen onuda izah edeyim;
PHP:
$KONTROL_EDILEN_DEGER ? $DOGRUYSA_CALISACAK_DEGER : $YANLISSA_CALISACAK_DEGER;
burada soru işareti if yerine geçer ve iki nokta üst üste ise elseyi ifade eder son olarak da satır tamamlandığı için noktalı virgül koyarız. soru işareti ile iki nokta üst üste olan kısımda hiçbir şekilde noktalı virgül kullanılmaz, çünkü ne kadar uzun bir kod yazsanız da bu ifade de satır else ile tamamlanacaktır. neyse, ne diyorduk metotun sonuna geldiğimizde ise, biz bir web sayfasına bağlanmak için istekte bulunduk ve haliyle bağlanmamışta olabiliriz, dolayısıyla aldığımız değeri kontrol ettiriyoruz ve eğer değer boş değilse gelen sonuçları gösteriyor veya kullanıyoruz, ama sonuç yok ise curl'un bağlanamadığına dair sınıf içerisinde yer alan hatalar metotu aracılığı ile bir hata göstererek geçerli komutların çalışmasını durduruyoruz.


PHP:
     public function SonucSayisi(){
        $resp = $this->Arama();
         preg_match('@<div id="result-found">(.*?)</div>@si', $resp, $sonuc); // bulunan sonuçların toplam sayısı
         preg_match('@<strong>(.*?)</strong>@si', $sonuc[0], $sonucsayisi); // bulunan sonuçların toplam sayısının metin değeri
         $ReturnToplamSonuc = str_replace(",", "", $sonucsayisi[1]);
         $Istatistikler = $sonucsayisi[1] > 0 ?
             (preg_match_all('@<div class="file-right">(.*?)</div>@si', $resp, $sonuclar) ?
              json_encode([
                  "toplam" => $ReturnToplamSonuc,
                  "gosterilen" => count($sonuclar[0]),
                  "sayfalar" => ceil($ReturnToplamSonuc / count($sonuclar[0]))
              ], JSON_UNESCAPED_UNICODE) : false
             ) : die($this->Hatalar(2,$this->Parametreler()->ara));
         return json_decode($Istatistikler);
     }

şimdi geldik ileride sizi en çok zorlayacak ve yaka silktirecek konuya. pregmatch. buradaki söz dizimi, diğer dillerin söz dizimlerine göre oldukça farklı ve zor. işin aslı kimisi kolayca kavrıyor, kimisi de benim gibi kavramasa da bir şekilde kullanmayı başarıyor : ) ne yapar bu pregmatch? bunu kod üzerinden anlatmadan önce göstererek anlatmak istiyorum.


mjw4hl2.jpg

biliyorsunuz ilk metotumuz Arama metotuydu ve curl ile arama sayfasına bağlanmıştık ve sonuçları bir dosyaya kaydetmiştik. Sonucsayisi metotunda ise, bu dosyadan aldığımız değerleri işlemeye başladık. bunu da pregmatch fonksiyonu ile gerçekleştirebiliriz. pregmatch belirtilen ifade içerisinde yer alan değerleri alır ve geri kalanını atar. bu değerlere erişmek için bu fonksiyonda regex denilen bir ifade kullanılır ve desen olarak tabir edilen kısım içerisinde yer alan değerler alınır. bunu daha iyi anlamak ve kullanımı için fonksiyon üzerinde çalışmanız gerekir. pregmatch ile pregmatch_all arasındaki fark ise, ilki eşleşen değerde durur ve sonuç verir, ikincisi ise eşleşen tüm değerleri bulur ve tüm değerleri sonuç olarak verir. iki sonuçta dizi halindedir.

neyse metota dönecek olursak, $Istatistikler değişkenine baktığımızda yine kısa bir if else yapısı kurduğumu ve bu sefer daha uzun bir şekilde iç içe kullandığımı fark etmişsinizdir. burada sayfanın sonuç kısmı değerlerini alarak işlem gerçekleştirdik, eğer siteye bağlanmada bir sorun yaşamadan aratma yaptıysak ve bu aşamaya kadar geldiysek, aradığımız kitap için sonuç olup olmadığını da kontro letmiş olduk bir yandan, yani bu if koşuluna baktığımızda
PHP:
         $Istatistikler = $sonucsayisi[1] > 0 ?
             "sonuç varsa hesaplamalar burada yapılıyor"
             : die($this->Hatalar(2,$this->Parametreler()->ara));
sonuç yok ise aramayla ilgili sonuç bulunamadığına dair bir uyarı göndererek kodların çalıştırılmasını durduruyoruz


PHP:
     public function RawResults(){
         $resp = $this->Arama();
         preg_match_all('@<div class="file-right">(.*?)</div>@si', $resp, $sonuclar);
         preg_match_all('@<img class="img-zoom file-img" src="(.*?)">@si', $resp, $resimler);
         return json_decode(json_encode([
             "sonuclar" => $sonuclar,
             "resimler" => $resimler
         ], JSON_UNESCAPED_UNICODE));
     }
Kod:
evet yine bir $this-Arama() ile metota başlıyoruz. görüyor musunuz cURL'un bağlantı isteği gerçekleştirği metotu ne kadar çok kullanıyoruz, eğer bunu dosyaya yazmamış olsaydık, kendi içerisinde yaşadığı bu döngü, belki de onlarca kez çalışmasına sebep olacaktı ve bu kadar curl isteğini tek bir komut dosyasında aynı anda gerçekleştirmek mümkün değil. bir üst metot da pregmatch kullanımına değinmiştim, bu sefer daha kapsamlı bir çalışma için ön hazırlık yapıyoruz. ve önce sayfada çıkan sonuçlar kısmınındaki değerleri yüzeysel olarak bir alıyoruz, daha sonrasında bunları tekrardan pregmatch değerinden geçirerk kullanacağız. neden birden fazla pregmatch kullanmak durumunda kaldık peki?
nlbbti9.jpg
burada gördüğünüz gibi her sonuç file-right class'lı bir divin içersinde kendi özellikleriyle alakalı değerler taşımakta, nedir bu değerler, kitap ismi, yazar adı, sayfa sayısı, boyutu ve diğerleri. biz önce büyük taşlar gibi bunları bi elekten geçirelim, daha sonra daha ufak taçlar için bir daha elekten geçireceğiz.


PHP:
     public function IdBul($value){
         $ids = explode('-', $value);
         $idsi = count($ids);
         $id = str_replace('.html', '', $ids[$idsi-1]);
         return $id;
     }
bu metot başka bir metot tarafından kullanılmak üzere id değerini bulması için verilen parametrede işlem gerçekleştirmek için yazılmış. çok söze gerek yok, kendi kendini gayet net anlatan basit bir işlem.


PHP:
     public function Kitaplar($value){
         $sonuclar = $this->RawResults()->sonuclar;
         $resimler = $this->RawResults()->resimler;
         $ReturnToplamSonuc = $this->SonucSayisi()->toplam;
         //ikinci dizeyi değiştir
         preg_match_all('@src="(.*?)"@si', $resimler[0][$value], $resim);
         preg_match_all('@<span class="fi-pagecount ">(.*?)</span>@si', $sonuclar[0][$value], $sayfa);
         preg_match_all('@<span class="fi-size hidemobile">(.*?)</span>@si', $sonuclar[0][$value], $boyut);
         preg_match_all('@<span class="fi-hit">(.*?)</span>@si', $sonuclar[0][$value], $okunma);
         preg_match_all('@<span class="fi-lang">(.*?)</span>@si', $sonuclar[0][$value], $dil);
         preg_match_all('@<a href="(.*?)"@si', $sonuclar[0][$value], $baglanti);
         preg_match_all('@<h2>(.*?)</h2>@si', $sonuclar[0][$value], $adveyazar);
         $adiyazari = explode(" - ", $adveyazar[1][0]); // bu değer bir üstteki preg_match'den oluştuğu için değiştirilmez
         return json_encode([
             "Adi" => strip_tags($adiyazari[0]),
             "Yazari" => !empty($adiyazari[1]) ? strip_tags($adiyazari[1]) : 'Belirtilmemiş',
             "Sayfasi" => !empty($sayfa[1][0]) ? str_replace(" Sayfa", "", $sayfa[1][0]) : "boş",
             "Boyutu" => $boyut[1][0],
             "Indirilme" => str_replace(array(",", " İndirme"), array("", ""), $okunma[1][0]),
             "Dili" =>  $dil[1][0],
             "Baglantisi" => $baglanti[1][0],
             "Kapagi" => $resim[1][0],
             "Id" => str_replace('e', '', $this->IdBul($baglanti[1][0]))
         ], JSON_UNESCAPED_UNICODE);
     }

evet, buradaki metotmuz ise RawResults metotundan aldığı değerleri bir kez daha pregmatch kullanarak istediğimiz biçime getirmek üzere çalışıyor. burada ufak taşları elekten geçiriyoruz işte, yazarın adını, kitabın adını, sayfasını ve benzeri bilgileri almak üzere işlem gerçekleştiriyoruz sadece.


PHP:
     public function KitaplariListele(){
         $Tekrarla = $this->SonucSayisi()->gosterilen;
         for ($x = 0; $x < $Tekrarla; $x++) {$sonuc[] = json_decode($this->Kitaplar($x), true);}
         //$sonuc[] = json_decode($this->Kitaplar(0), true);
         $donustur = ["Durum" => "true", "ToplamSonuc" => $this->SonucSayisi()->toplam, "GosterilenSonuc" => $this->SonucSayisi()->gosterilen, "Kitaplar" => $sonuc];
         header('Content-Type: application/json; charset=utf-8');
         echo json_encode($donustur,JSON_UNESCAPED_UNICODE);
     }
bir bot yazmaya karar verdiyseniz eğer, döngüleri biliyor olduğunuzu düşünüyorum. çünkü döngüler herhangi bir dilde temel olarak öğretilen fonksiyonlardır. buradaki metot isminden de anlaşılacağı üzere kitapları listelemek üzere SonucSayisi metotundan aldığı int değere göre bir döngü oluşturuyor, daha sonrasında x kitap sayısına ulaşıncaya kadar tekrarlanıyor. json formatında tarayıcıya çıktı olarak aktarılıyor.


PHP:
     public function Hatalar($value, $arama=''){
         $value = $value == 1 ? ["Durum" => "false", "hata" => "curl bağlanamadı lütfen tekrar deneyin"] :
         ($value == 2 ? ["Durum" => "false", "hata" => urldecode($arama)." arama için sonuç bulunamadı"] :
          ($value == 3 ? ["Durum" => "false", "hata" => "sorgu için sadece q parametresini kullan"] :
           ["Durum" => "false", "hata" => "parametre belirtilmemiş"])
         );
         return json_encode($value, JSON_UNESCAPED_UNICODE);
     }
hata demek aslında doğru olmaz, karşılaşılacak olası olumsuz durumlar için yanıtlarımızı bu metotda oluşturarak, diğer metotlarda die fonksiyonu içerisine daha az komut yazmış olduk. yoksa bunun için metot gerekli bir şey değildi ama, birden fazla hata durumu senaryosu varsa, tek bir yerde toplayıp, bunlara hata 1, hata 2 diye numara vermek daha verimli olur diye düşündüm.

PHP:
     public function __construct(){
         $_GET ? (isset($_GET["q"]) ? $this->KitaplariListele() : die($this->Hatalar(3)) ) : die($this->Hatalar(4));
     }

geldik yapıp yanı sınıfın ilk çalıştıracağı metota, bunu en son anlatmak normal aslında, çünkü bu metot enson yazılan metot. kendinden önce gelen bütün metotları arka planda zaten çalıştırıyor çünkü. size kısa if else kullanımdan bahsetmiştim. burada bir get isteği varsa ve bu get isteği q parametresini alıyorsa kitaplar listelenecek, koşullardan sağlanmayan olursa duruma uygun hatalar yazılacak. Şimdi yazdığım bu sayfayı çalıştırayım bakalım ne olacak.

varsayalım ki linkimiz localhost/index.php

localhost/index.php'e istekte bulunduğumda alacağım sonuç aşağıdaki gibi çıkacak;
JSON:
{
"Durum": "false",
"hata": "parametre belirtilmemiş"
}

isteyerek yanlış parametre belirttiğimi varsayalım localhost/index.php?test=merhaba
JSON:
{
"Durum": "false",
"hata": "sorgu için sadece q parametresini kullan"
}

bu sefer doğru parametreyi kullanayım ama değer tanımlamayım localhost/index.php?q=
JSON:
{
"Durum": "false",
"hata": "en az 4 karakter içeren bir arama yapın"
}

eğer curl olurda bağlantı kurmakta sorun yaşasaydı bu sefer şöyle bir çıktı alacaktık
JSON:
{
"Durum": "false",
"hata": "curl bağlanamadı lütfen tekrar deneyin"
}

gelelim gerçek arama yapma kısmına diyelim ki Turk Hack Team ile alakalı bir şey arıyoruz localhost/index.php?q=Turk+Hack+Team
JSON:
{
"Durum": "false",
"hata": "Turk Hack Team arama için sonuç bulunamadı"
}

bu sefer de Attila İlhan diye arama yapalım localhost/index.php?q=Attila+İlhan

JSON:
{
"Durum": "true",
"ToplamSonuc": "74",
"GosterilenSonuc": 18,
"Kitaplar": [
{
"Adi": "Sisler Bulvarı",
"Yazari": "Attila İlhan",
"Sayfasi": "213",
"Boyutu": "501 KB",
"Indirilme": "8389",
"Dili": "Türkçe",
"Baglantisi": "\/sisler-bulvarı-attila-İlhan-e118312356.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/6b1\/6b16fa39cb7c4a757562c85e06fe4a66-s.jpg",
"Id": "118312356"
},
{
"Adi": "Elde Var Hüzün",
"Yazari": "Attila İlhan",
"Sayfasi": "187",
"Boyutu": "537 KB",
"Indirilme": "6039",
"Dili": "Türkçe",
"Baglantisi": "\/elde-var-hüzün-attila-İlhan-e118312377.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/868\/868d6cc8243bca69adb4be04340b5c2a-s.jpg",
"Id": "118312377"
},
{
"Adi": "Attilâ İlhan _ Ben Sana Mecburum",
"Yazari": "Belirtilmemiş",
"Sayfasi": "78",
"Boyutu": "267 KB",
"Indirilme": "4663",
"Dili": "Türkçe",
"Baglantisi": "\/attilâ-İlhan-_-ben-sana-mecburum-e61306406.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/43b\/43be615e12ac168f1aeb9efba8254816-s.jpg",
"Id": "61306406"
},
{
"Adi": "Yasak Sevişmek",
"Yazari": "Attila İlhan",
"Sayfasi": "142",
"Boyutu": "553 KB",
"Indirilme": "3691",
"Dili": "Türkçe",
"Baglantisi": "\/yasak-sevişmek-attila-İlhan-e118312405.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/3c9\/3c9480d323ef46eed81a5dbee0b7b7e2-s.jpg",
"Id": "118312405"
},
{
"Adi": "Bıçağın Ucu",
"Yazari": "Attilâ İlhan",
"Sayfasi": "518",
"Boyutu": "1.8 MB",
"Indirilme": "2996",
"Dili": "Türkçe",
"Baglantisi": "\/bıçağın-ucu-attilâ-İlhan-e117481988.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/458\/458ce06e785c43663fdd3323fbda30c6-s.jpg",
"Id": "117481988"
},
{
"Adi": "Hangi Atatürk",
"Yazari": "Belirtilmemiş",
"Sayfasi": "398",
"Boyutu": "10.34 MB",
"Indirilme": "6143",
"Dili": "Türkçe",
"Baglantisi": "\/hangi-atatürk-e62352353.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/854\/854be2e42ad52a7e735fd22f08f0ca6a-s.jpg",
"Id": "62352353"
},
{
"Adi": "Attilâ İlhan Ben Sana Mecburum",
"Yazari": "aksoymustafa.com",
"Sayfasi": "78",
"Boyutu": "267 KB",
"Indirilme": "173",
"Dili": "Türkçe",
"Baglantisi": "\/attilâ-İlhan-ben-sana-mecburum-aksoymustafacom-e18526800.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/7c1\/7c1a8c040c00880a31d3ff829914f16f-s.jpg",
"Id": "18526800"
},
{
"Adi": "ATTİLÂ İLHAN Bütün Şiirleri 2 SİSLER BULVARI",
"Yazari": "Belirtilmemiş",
"Sayfasi": "79",
"Boyutu": "332 KB",
"Indirilme": "191",
"Dili": "Türkçe",
"Baglantisi": "\/attİlÂ-İlhan-bütün-Şiirleri-2-sİsler-bulvari-e18525893.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/ecb\/ecbd8d83e60022e5b9d28da39d5fe274-s.jpg",
"Id": "18525893"
},
{
"Adi": "Attilâ Ilhan",
"Yazari": "Belirtilmemiş",
"Sayfasi": "16",
"Boyutu": "5.39 MB",
"Indirilme": "36",
"Dili": "Türkçe",
"Baglantisi": "\/attilâ-ilhan-e61529567.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/8f4\/8f40614aced5a40dcd81dd925d939712-s.jpg",
"Id": "61529567"
},
{
"Adi": "Attila İlhan",
"Yazari": "Duvar",
"Sayfasi": "boş",
"Boyutu": "2.55 MB",
"Indirilme": "137",
"Dili": "Türkçe",
"Baglantisi": "\/attila-İlhan-duvar-e200733156.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/d0c\/d0c5b28ee262295fbed45e53a2c86cf3-s.jpg",
"Id": "200733156"
},
{
"Adi": "Didem Gözükaraoğlu.pdf",
"Yazari": "Belirtilmemiş",
"Sayfasi": "1,370",
"Boyutu": "7.29 MB",
"Indirilme": "28",
"Dili": "Türkçe",
"Baglantisi": "\/didem-gözükaraoğlupdf-e62274290.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/65e\/65ebdc8c6ca7a8e2d21387a6b29c612a-s.jpg",
"Id": "62274290"
},
{
"Adi": "attıla îlhan",
"Yazari": "Belirtilmemiş",
"Sayfasi": "471",
"Boyutu": "14.48 MB",
"Indirilme": "408",
"Dili": "Türkçe",
"Baglantisi": "\/attıla-îlhan-e62352237.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/fbe\/fbe9eea0e81e5a33f5e5c577f7b47901-s.jpg",
"Id": "62352237"
},
{
"Adi": "Sisler Bulvarı",
"Yazari": "Belirtilmemiş",
"Sayfasi": "129",
"Boyutu": "449 KB",
"Indirilme": "345",
"Dili": "Türkçe",
"Baglantisi": "\/sisler-bulvarı-e60989164.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/155\/155cf8f3f902fb08fb9056a97554490e-s.jpg",
"Id": "60989164"
},
{
"Adi": "Hangi Atatürk",
"Yazari": "Belirtilmemiş",
"Sayfasi": "398",
"Boyutu": "10.69 MB",
"Indirilme": "330",
"Dili": "Türkçe",
"Baglantisi": "\/hangi-atatürk-e179441718.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/715\/715656bf3d16f8c33d5964f521df6355-s.jpg",
"Id": "179441718"
},
{
"Adi": "Türkiye Solunda Bir Figür Olarak Attila İlhan",
"Yazari": "Belirtilmemiş",
"Sayfasi": "30",
"Boyutu": "357 KB",
"Indirilme": "17",
"Dili": "Türkçe",
"Baglantisi": "\/türkiye-solunda-bir-figür-olarak-attila-İlhan-e197337225.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/821\/8210670edc859509916d06a4303a96a2-s.jpg",
"Id": "197337225"
},
{
"Adi": "Attila İlhan'ın ''Ağustos Çıkmazı'",
"Yazari": "Belirtilmemiş",
"Sayfasi": "20",
"Boyutu": "17.18 MB",
"Indirilme": "14",
"Dili": "Türkçe",
"Baglantisi": "\/attila-İlhanın-ağustos-Çıkmazı-e61306219.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/2d1\/2d1847b91747a1a0d2c866c6e417d507-s.jpg",
"Id": "61306219"
},
{
"Adi": "tutuklunun aünlüğü",
"Yazari": "Belirtilmemiş",
"Sayfasi": "185",
"Boyutu": "1.69 MB",
"Indirilme": "241",
"Dili": "Türkçe",
"Baglantisi": "\/tutuklunun-aünlüğü-e52791314.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/f06\/f06e86ae901f153f43f9a631ee95eebb-s.jpg",
"Id": "52791314"
},
{
"Adi": "Elde Var Hüzün",
"Yazari": "Belirtilmemiş",
"Sayfasi": "106",
"Boyutu": "390 KB",
"Indirilme": "150",
"Dili": "Türkçe",
"Baglantisi": "\/elde-var-hüzün-e47853331.html",
"Kapagi": "https:\/\/cdn.asaha.com\/assets\/thumbs\/404\/40408d179f23290f8dd21b01e1596258-s.jpg",
"Id": "47853331"
}
]
}
birde siteye bakalım aynı arama esnasında
o7bjmnz.jpg

gördüğünüz gibi artık sitenin arama sayfasındaki tüm değerler için json olarak yanıt verebileceğim bir yapıya sahibim. devamın ise konunun başında söylediğim şekilde, yanıtları doğrultusunda sunucu sunucu gezip kitap avlayacağız ve bu kitapları kendi sunucumuza çekerek ister pdf olarak görüntüleyip, ister text olarak görüntüleyip, istersekte dinleyebileceğiz.
 
Son düzenleme:
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.