Forum: Ders Arası RSS
Html işler kütüphane
Sayfa:  1  2  sonraki 
erdem (Moderatör) #1
Üye Tem 2009 tarihinden beri · 894 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Html işler kütüphane
http://ddili.org/forum/post/12299

adresinde konuştuğumuz konuya kimse yanıt yazmamış.

Ben de bu arada html işler bir kütüphane yazması denemesi yaptım.

import std.stdio;
import std.format;
import std.array : replicate;
 
class Kiraz
{
    private int no =  0;
    private int sayaç;
    private int elemanSayısı;
    private int[] kök;
    private Dal[] dallar;
 
    this (int n)
    {
        elemanSayısı = n;
        sayaç = n;
 
        kök = new int[n];
        dallar =  new Dal[n];
 
        for(int i = 0; i < n; ++i)
        {
            kök[i] = i;
        }
 
    }
 
    private int bul(int i)
    {
        while (i != kök[i])
            i = kök[i];
        return i;
    }
 
 
    void bağla(int ilk, int ikinci)
    {
        int ilkDal = bul(ilk);
        int ikinciDal = bul(ikinci);
        if (ilkDal == ikinciDal)
            return;
        kök[ilkDal] = ikinci;
        --sayaç;
    }
 
 
    void ekle(string isim, int derinlik)
    {
 
 
        if (no == 0)
        {
            dallar[no].no = no;
            dallar[no].isim = isim;
            dallar[no].derinlik = derinlik;
            writeln("İlk kez ekliyorum");
 
        }
        else
        {
            dallar[no].no = no;
            dallar[no].isim = isim;
            dallar[no].derinlik = derinlik;
            writeln("Başka dallar ekliyorum");
 
 
            if (dallar[no-1].derinlik < dallar[no].derinlik)
            {
                writeln("alt dal");
                bağla(dallar[no].no, dallar[no-1].no);
                dallar[no].üstDal = dallar[no-1].no;
                dallar[no-1].dallar ~= dallar[no].no;
 
            }
            else if (dallar[no-1].derinlik == dallar[no].derinlik)
            {
                writeln("yan dal");
                if (dallar[no - 1].üstDal != -1)
                {
                    bağla(dallar[no].no, dallar[no - 1].üstDal);
                    dallar[no].üstDal = dallar[no - 1].üstDal;
                    dallar[dallar[no].üstDal].dallar ~= dallar[no].no;
                }
 
            }
 
        }
 
        writeln("Dallarımız = ");
 
        foreach (eleman; dallar)
            writeln (eleman);
 
        ++no;
    }
 
    override string toString() const
    {
        string dönen;
 
        for(int i = 0; i < elemanSayısı; ++i)
        {
            dönen ~= format("%2s", i);
        }
 
        dönen ~= '\n';
 
 
        string çizgi = " -".replicate(elemanSayısı);
        dönen ~= çizgi;
        dönen ~= '\n';
 
        for(int i = 0; i < elemanSayısı; ++i)
        {
            dönen ~= format("%2s", kök[i]);
        }
        dönen ~= '\n';
        return dönen;
 
    }
 
}
 
struct Dal
{
    string isim;
    int derinlik;
    int no;
    int üstDal = -1;
    int[] dallar;
 
    string toString() const
    {
        string dönen;
        dönen ~= format("İsim = %2s Derinlik = %2s Üst Dal = %2s Dallar = %2s", isim, derinlik, üstDal, dallar);
        return dönen;
    }
}
 
void main()
{
    string html =
        `<ul id="meyveler">
         <li class="elma">Elma</li>
         <li class="portakal">Portakal</li>
         <li class="incir">İncir</li>
         </ul>`;
 
    /+ 
    ul 0
    li 1
    li 1
    li 1
    +/
 
    Kiraz kiraz = new Kiraz(4);
    kiraz.ekle("ul", 0);
    writeln(kiraz);
    kiraz.ekle("li", 1);
    writeln(kiraz);
 
    kiraz.ekle("li", 1);
    writeln(kiraz);
 
    kiraz.ekle("li", 1);
    writeln(kiraz);
}

Şimdi asıl soru şu bu şekilde bir sınıfa geçilen html kodundan
         <ul id="meyveler">
         <li class="elma">Elma</li>
         <li class="portakal">Portakal</li>
         <li class="incir">İncir</li>
         </ul>

{ ul 0, li 1, li 1, li 1} gibi elemanların derinliklerini gösteren bir ifadeyi nasıl elde edebiliriz. Biz bu ifadeyi gördüğümüzde hemen diyoruz ki meyveler en dışta.

Bu arada sınıf için ağaç veri yapısı oluşturmaya çalıştım. Elemanların derinliğine göre eklenmesi isteniyor.
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4389 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ağaç yapısı oluşturmanın en kolayı, dalları ve düğümleri aynı türden yapmaktır. Düşününce, zaten her düğümün de aslında bir ağaç olduğu görülüyor. Benim çok uyduruk deneysel bir projemde öyle:

  https://github.com/acehreli/alibum/blob/master/html.d

Genel olarak, web kütüphanelerinde Adam Ruppe'nin kütüphanelerinin işe yaradığını duyuyorum. Kendisi bunları profesyonel olarak da kullanıyor. En azından fikir alınabilir:

  https://github.com/adamdruppe?tab=repositories

ekle() işlevini yazmanın en kolay (ama bazen kafa karıştırabilen) yolu, her ağaç işlevinde olduğu gibi özyineleme kullanmaktır. Yapman gereken, hangi çocuğa gideceğini bulmak ve o çocuğa ekle(derinlik - 1) demektir. Ama senin bir sorunun, çocuğu baştan söylemiyor oluşun. Dolayısıyla, en üst düzeye "şu derinliğe ekle" demek belki de doğru tasarım değil. (?)

Ali
erdem (Moderatör) #3
Üye Tem 2009 tarihinden beri · 894 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Sanırım haklısınız ağaç veri yapısını sınıftan ayırmak daha iyi bir fikir gibi gözüküyor.

Bahsettiğiniz kütüphaneyi inceledim.

    auto içerik = getContent("http://www.biradres.com");
 
    auto kütük = File("deneme.html", "w");
    kütük.rawWrite(içerik.data);
    kütük.close();
    
    kütük = File("deneme.html", "r+");
    kütük.writeln("\n");
    
    kütük.writeln("<html>");

Şimdi veriyi ubyte[] olarak alıyorum. Kütüğe yazıyorum.

arsd.dom kütüphanesi'nin en başa html etiketleri yazılmadan verileri işleyemediğini farkettim. Bu nedenle kütüğün sonuna ve başına <html> gibi etiketler yazmak gerekiyor.

Ama sorun şu ki bu şekilde yazınca baştan bazı karakterleri yiyor. Örneğin:

<html>
s="sectionedit1" id="Arduino_baslangıc">Arduino başlangıç</h1>
<div class="level1">

Olmasını temenni ettiğimiz

<html>
<h1 class="sectionedit1" id="Arduino_baslangıc">Arduino başlangıç</h1>
<div class="level1">

Bunu önlemenin bir yolu var mı acaba.
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4389 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
<html>'i rawWrite'tan önce yazamaz mısın? Ama daha iyisi, getContent'le elde edilen veriyi HTML gibi bir türe versen ve başını sonunu o koysa? Tam olarak hangi kütüphaneyi kullandığını anlamadım ama o dizinde "html" diye aratırsan belki de bunu yapan bir işlevleri zaten vardır.

Ali
erdem (Moderatör) #5
Üye Tem 2009 tarihinden beri · 894 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Tamam Ali bey şimdi hallettim.
    string veriler;
    veriler ~= `<html>`;
    veriler ~= `<head>`;
    veriler ~= `</head>`;
    veriler ~= `<body>`;
 
    while (!kütük.eof())
    {
        veriler ~= (strip(kütük.readln()));
        veriler ~= '\n';
 
    }
 
    veriler ~= `</body>`;

Ben de ilkönce html başlık kısmını bir dizgiye ekledim.

Verileri ubyte[] olarak almak için bu kütüphaneyi kullanıyorum.

https://github.com/ikod/dlang-requests
acehreli (Moderatör) #6
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4389 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Çözdüğüne sevindim. :) Anladığım kadarıyla o kütüphane bu işle ilgilenmiyor; amaçları request/response. O yüzden <html> vs. için olanak sunmamışlar (galiba).

Ali
erdem (Moderatör) #7
Üye Tem 2009 tarihinden beri · 894 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Peki Ali bey örnek olsun diye şu şekilde bir .txt dosyamız var.
h2:class id
span:
img:class id src

    auto kütük = File("veri/wiki_temizle.txt", "r");
 
    foreach (satır; kütük.byLine())
    {
        string isim;
        string özellik;
 
        formattedRead(satır, " %s: %s", &isim, &özellik);
        writeln("İsim = ", isim);
        writeln("Özellik = ", özellik);
    }

Ben bu ikinci dizgeyi parçalayınca yapmak istediğimi sanırım yapabiliyorum. Ama biraz da öğrenmek için soruyorum.

Burada formattedRead'e string yerine string[] ya da string[string]'e de okuma yaptırabilirmiydik.
erdem (Moderatör) #8
Üye Tem 2009 tarihinden beri · 894 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Bir de ilginç bir şekilde range error hatası alıyorum.

core.exception.RangeError@temizle.d(35): Range violation
struct Eleman
{
    string isim;
    string[] özellikler;
}
 
 
Document sayfaTemizle(Document belge)
{
    auto kütük = File("veri/wiki_temizle.txt", "r");
    Eleman[] elemanlar;
 
    uint i = 0;
    foreach (satır; kütük.byLine())
    {
        string isim;
        string veri;
 
        formattedRead(satır, " %s: %s", &isim, &veri);
        string[] özellikler =  veri.split();
        writeln("İsim = ", isim);
        writeln("Veri", veri);
        writeln("Özellikler = ", özellikler);
        elemanlar[0].isim = "ahmet"; <-- burası hata veriyor
 
        // elemanlar[i].isim = isim;
        // elemanlar[i].özellikler = özellikler;
        writeln("i =", i);
        ++i;
    }
   /* ... */
}
erdem (Moderatör) #9
Üye Tem 2009 tarihinden beri · 894 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
struct Eleman
{
    string isim;
    string[] özellikler;
}
 
 
Document sayfaTemizle(Document belge)
{
    auto kütük = File("veri/wiki_temizle.txt", "r");
    Eleman[] elemanlar;
 
    uint i = 0;
    foreach (satır; kütük.byLine())
    {
        string isim;
        string veri;
        Eleman eleman;
 
        formattedRead(satır, " %s: %s", &isim, &veri);
        string[] özellikler =  veri.split();
        eleman.isim = isim;
        eleman.özellikler = özellikler;
        elemanlar ~= eleman;
        ++i;
    }
 
    foreach (eleman; elemanlar)
    {
        writeln ("isim = ",  eleman.isim);
        writeln ("özellikler = ", eleman.özellikler);
    }
 
    auto h2 = belge["h2"];
    foreach (başlık; h2)
    {
        başlık.removeAttribute("class");
    }
    return belge;
}

Bu çalıştı.  :-) Ama bu verileri eleman yapısına atmanın daha kolay bir yolu var mı acaba.

Bir de bir önceki hata iletisi vermesi normal mi.
acehreli (Moderatör) #10
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4389 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Önce bir uyarı: byLine satırları hep aynı ara belleğe okur. Dolayısıyla, satırın içindeki bir veriyi elinde tutmak istiyorsan, örneğin saklanan = satır[x..y] yapamazsın çünkü bir sonraki satır okununca aynı yerin üstüne yazılabilir. O yüzden, kopyalaman gerekir: saklanan = satır[x..y].idup (veya duruma göre .dup).

Başka yöntem, byLine değil, byLineCopy kullanmaktır. Bu, her satırı yeni belleğe okur. Hangi yöntemin daha iyi olduğuna duruma göre karar verilebilir. Örneğin, byLineCopy bütün satırı tek kere kopyalar ve sen mutlu mutlu saklanan = satır[x..y] yapabilirsin.

formattedRead, formattedWrite'ın yazabildiği çoğu şeyi (herşeyi?) okumalı:
import std.stdio;
import std.format;
 
void main() {
    string[] dizi;
    string satir = `[ "abc", "xyz" ]`;
    formattedRead(satir, "%s", &dizi);
    writeln(dizi);
}
Başka yöntemler de var: splitter, regex, vs.

(Bunu zaten sonradan düzeltmişsin.) elemanlar dizisiyle ilgili hata bariz. :) elemanlar'a hiç eleman eklemeden ilk elemanına erişmeye çalışıyorsun. Şöyle olabilir:
    elemanlar ~= Eleman("ahmet");    // Artık elemanı var 
Ama bazen böyle döngüyle uğraşmak yerine zincirleme çağrılar öneriliyor:
import std.algorithm : findSplit;
import std.range.primitives : isInputRange;
import std.algorithm : map, filter, each, splitter;
import std.stdio : writefln;
import std.array : array;
 
struct Eleman(Özellikler) if (isInputRange!Özellikler) {
    string isim;
    Özellikler özellikler;
}
 
// Yalnızca bir kolaylık işlevi; kodda eleman(a, b) diye oluşturabiliyoruz
auto eleman(Özellikler)(string isim, Özellikler özellikler) {
    return Eleman!Özellikler(isim, özellikler);
}
 
void main() {
    auto satırlar = [ "h2:class id", "span:", "img:class id src", "istenmeyen: foo" ];
 
    auto elemanlar = satırlar
                     .map!(satır => satır.findSplit(":"))  // çokuzlu döndürür; ç diyorum:
                     .filter!(ç => ç[0] != "istenmeyen")
                     .map!(ç => eleman(ç[0], ç[2].splitter));
 
    // Şimdi 'elemanlar' tembelce oluşturulan bir aralıktır
    writefln("Okunan elemanlar: %s", elemanlar);
 
    // Ama istersek örneğin hepsinden oluşan bir dizi oluşturabiliriz:
    auto dizi = elemanlar.array;
 
    writefln("Oluşturulan dizi: %-(%s, %)", dizi);
}
Duruma göre bu çok daha iyi olabiliyor çünkü bu örnekte örneğin bütün elemanları writefln ile yazdırabildiğimiz halde hiçbirisi için yer ayırmak zorunda kalmadık. Milyonlarca eleman olduğunda az bellek kullandırdığından bu yöntem daha hızlıdır.

Ali
erdem (Moderatör) #11
Üye Tem 2009 tarihinden beri · 894 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
formattedRead, formattedWrite'ın yazabildiği çoğu şeyi (herşeyi?) okumalı:
import std.stdio;
import std.format;
 
void main() {
    string[] dizi;
    string satir = `[ "abc", "xyz" ]`;
    formattedRead(satir, "%s", &dizi);
    writeln(dizi);
}

Peki Ali bey iki tane değişken olursa.

import std.stdio;
import std.format;
 
void main() {
    string isim;
    string[] dizi;
 
    string satir = `[ "h2:class id", "span:" ]`;
    formattedRead(satir, " %s: %s", &isim, &dizi);
    writeln(dizi);
}

Bu şekilde derlemeye çalışınca bu hatayı alıyorum.

std/conv.d(3390): Can't parse string: "[" is missing
acehreli (Moderatör) #12
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4389 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
O satırda isim eksik. Şu oluyor:
    string satir = `"erdem": [ "h2:class id", "span:" ]`;
Ali
erdem (Moderatör) #13
Üye Tem 2009 tarihinden beri · 894 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ali bey teşekkürler! :)

Gerçi eleman yapısının parametrelerini dizge olarak değiştirdim. Ama gene de formattedRead ile dizilerin de okunabildiğini öğrenmem iyi oldu.

Yazım biçimini biraz değiştirdim. Şimdi yazım biçimlerini ayırt eden kısım üzerinde çalışıyorum.

h2:class id
span:
td:class=.1
img:class=manzara


Örneğin span: tamamen bir etiketi siliyor. <span></span> ya da <span class="deneme">yazı </span> --> yazı oluyor.

h2:class id ise h2 etiketinin class ve id özellikleri siliyor. Etiket ve varsa diğer özellikler duruyor.

td:class=.1 ise sadece ilk özelliğin  değerini siliyor. <td class="çorba ekmek limon"></td> ilk özellik değeri silindikten sonra <td class="ekmek limon"></td> oluyor.

img:class=manzara ise nasip olursa sadece sınıfı manzara olan özelliği silecek.
struct Eleman
{
    this(string isim, string özellikler, string eski = "")
    {
        this.isim = isim;
        this.özellikler = özellikler.split();
        this.eski = eski;
        if (this.özellikler.length == 1 && indexOf(dizgeYap(this.özellikler), "=") > 0)
            if (indexOf(dizgeYap(this.özellikler), ".") > 0)
                ilkDeğeriSil_ = true;
            else
                özellikSil_ = true;
    }
 
    string isim;
    string[] özellikler;
    string eski;
 
    bool ilkDeğeriSil_ = false;
    bool özellikSil_ = false;
 
    bool ilkiSil () const @property
    {
        return ilkDeğeriSil_;
    }
    bool özellikSil () const @property
    {
        return özellikSil_;
    }
}
erdem (Moderatör) #14
Üye Tem 2009 tarihinden beri · 894 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Adresleri okuyan bir yapı üzerinde çalışıyorum.

struct Adres
{
    import std.string;
    import std.algorithm;
    import std.stdio;
 
    private
    {
        string sunucu_;
        string adres_;
        string kök_;
        string kütük_;
        string[] dizinler_;
        string iletişimKuralı_;
    }
 
    this (string adres, int derinlik = 0)
    {
        adres_ = adres;
        auto işlenen = adresİşle(adres, derinlik);
 
        if (!işlenen)
        {
            throw new Exception("Adresi işleyemiyorum" ~ adres_);
        }
 
    }
 
    bool adresİşle(string adres, int derinlik)
    {
        auto i = adres.findSplit("://");
        string kalan;
        if (i[1].length)
        {
            iletişimKuralı_ = i[0].toLower;
            kalan = i[2];
        }
        else
        {
            return false;
        }
 
        string kök;
 
        sunucu_ = kalan.findSplit("/")[0];
 
 
        for(int k = 0; k < derinlik + 1; ++k)
        {
            i = kalan.findSplit("/");
            kök ~=  i[0] ~ i[1];
            kök_ = "%s://%s".format(iletişimKuralı_, kök[0..$ - 1]);
            kalan = i[2];
        }
 
        auto dizinler = split(kalan, "/");
 
        for(int j = 0; j < dizinler.length - 1; ++j)
        {
            dizinler_ ~= dizinler[j];
        }
 
        kütük_ = dizinler[dizinler_.length];
 
        return true;
    }
}
 
unittest
{
    auto a = Adres("http://www.erdem.tk/wiki/html/arduino/arduinobaslangic.html", 3);
}

Böylelikle oluşturulacak dizinler arasında

    foreach(dizin; adres.dizinler)

şeklinde gezilebilir. Bunu da ddili'ni aktarmaya çalışırken farkettim. Örneğin benim sitem tek bir derinlik kullanıyor.

Ama

http://ddili.org/ders/d/index.html

şeklinde bir adresi işlerken ders -> d vs.. şeklinde diğer alt dizinleri de oluşturması gerekiyor.

Yerel dizinleri ya da uzak dizinleri oluştururken de böyle gezdiğimiz dizinleri takip eden bir yapı sizce faydalı olur mu.

void tekSayfaOluştur(Document belge)
{
    yerelDiziniOluştur();
    auto sayfaBaşlığı = belge["h1"][0].innerText;
    writeln(sayfaBaşlığı);
}
 
void yerelDiziniOluştur()
{
    adımAt("veri");
    adımAt("yerel");
}
 
void adımAt(string dizin)
{
    if (exists(dizin))
    {
        chdir(dizin);
    }
    else
    {
        mkdir(dizin);
        chdir(dizin);
    }
}
acehreli (Moderatör) #15
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4389 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
derinlik parametresine gerek olmamalı. Sanırım std.path modülü işine yarayabilir: baseName, dirName, ve arkadaşları... Gerekirse, mkdir'e ek olarak mkdirRecurse olduğunu da hatırlatırım.

Ufak bir basitleştirme:
void adımAt(string dizin)
{
    if (!exists(dizin))
    {
        mkdir(dizin);
    }
    chdir(dizin);
}
Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  1  2  sonraki 
Forum: Ders Arası RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-03-23, 11:19:05 (UTC -07:00)