# Code zu einem Projekt entschluesseln



## kevla (26. Okt 2013)

Hallo zusammen,

fuer ein Projekt sollte ich die Anzahl von Bildern, Wörtern, Links und Eingabefeldern auf einer Datenbank eines Servers von tausenden durch HTTRACK gespeicherten Webseiten herauslesen.

Ich habe annaehernd das, was ich gewuenscht hatte durch einen befreundeten Programmierer umgesetzt bekommen und schicke hiermit den Code, denn vielleicht kann jemand detaillerter beschreiben, was genau dort gemacht wurde. Denn ich habe mir zwar einige Notizen gemacht und er hat ja auch ein paar Kommentare im Code hinterlassen, ich als Javaneuling verstehe dennoch trotzdem wenig, was dort im Detail gemacht wurde. So bin ich mir jetzt selbst ueber die Quelle nicht mehr sicher, er muesste eine Library von Jsoup implementiert haben, es koennte die commons-io-2.4-bin.zip sein, weil ich diese gerade noch auf dem Rechner finde. Naja aber auch sonst eine einfache Erklaerung zu den Zeilen wuerde mir stark helfen, es ist ja nicht besonders viel Code, bis jetzt weiss ich nur, dass bei der Ausgabe 4 Elemente einer Webseite gezaehlt werden. Woerter, Bilder, Links und Eingabefelder, aber auf welcher Grundlage dies beruht wuerde ich gerne auch noch verstehen. Ich weiss nur noch, dass er meinte, dass es schwierig ist zu definieren, was nun genau ein Bild auf einer Webseite ist, also zaehlen auch Buttons dazu oder auch kleine Icons, das selbe bei den Worten, wird nur allgemeiner Text gezaehlt oder jedes einzelne Wort. Nun ja vielleicht kann ja jemand diesen Code in einfache Worte fassen, wuerde mich retten, vielen vielen Dank schon mal!!

Kevla

Hier der Code:


```
package org.jsoup.examples;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.jsoup.Jsoup;
import org.jsoup.helper.StringUtil;
import org.jsoup.helper.Validate;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
import org.jsoup.select.NodeTraversor;
import org.jsoup.select.NodeVisitor;

/**
 * HTML to plain-text. This example program demonstrates the use of jsoup to convert HTML input to lightly-formatted
 * plain-text. That is divergent from the general goal of jsoup's .text() methods, which is to get clean data from a
 * scrape.
 * <p/>
 * Note that this is a fairly simplistic formatter -- for real world use you'll want to embrace and extend.
 *
 * @author Jonathan Hedley, [email]jonathan@hedley.net[/email]
 */
public class HtmlTextExtractor {
    private static final String HTRACK_INDEX_END_MARKER = "\"";
    private static final String HTTRACK_INDEX_NAME = "index.html";
    private static final String HTTRACK_INDEX_START_MARKER = "URL=";
    public static void main(String... args) throws IOException {
        Validate.isTrue(args.length == 1, "usage: supply path to process");
        String dir = args[0];
        File repo = new File(dir);
        System.out.println("Website,Words,Links,Images,Inputs");
        for(String name:repo.list()) {
            if (new File(repo, name).isDirectory()) {
                oneWebsite(repo, name);
            }
        }
    }

    private static void oneWebsite(File repo, String name) throws IOException {
        File dir = new File(repo, name);
        try {
            File indexFile = getIndexPath(dir);
            Document doc = Jsoup.parse(indexFile, null);
            if (isFrameset(doc)) {
                System.out.printf("%s,Frameset\n", name);
            } else {
                HtmlTextExtractor formatter = new HtmlTextExtractor();
                String plainText = formatter.getPlainText(doc);

                System.out.printf("%s,%d,%d,%d,%d\n", name,
                        countWords(plainText),
                        countLinks(doc),
                        countImages(doc),
                        countInputFields(doc));
            }
        } catch (FileNotFoundException e) {
            System.out.printf("%s,No httrac index file\n", name);
        }
    }

    private static File getIndexPath(File dir) throws IOException, FileNotFoundException {
        File httrackIndex = new File(dir, HTTRACK_INDEX_NAME);
        FileInputStream inputStream = new FileInputStream(httrackIndex);
        try {
            String everything = IOUtils.toString(inputStream);
            int urlIndex = everything.indexOf(HTTRACK_INDEX_START_MARKER) + HTTRACK_INDEX_START_MARKER.length();
            int urlLastIndex = everything.indexOf(HTRACK_INDEX_END_MARKER, urlIndex);
            return new File(dir, everything.substring(urlIndex, urlLastIndex));
        } finally {
            inputStream.close();
        }
    }

    private static boolean isFrameset(Document doc) {
        Elements framesets = doc.select("frameset");
        return framesets.size() > 0;
    }
    
    private static int countWords(String text) {
        boolean inWord = false;
        int count = 0;
        int len = text.length();
        
        for (int i = 0; i < len; i++) {
            final char c = text.charAt(i);
            switch (c) {
                case ' ':
                case '\t':
                case '\n':
                    if (inWord) {
                        count++;
                    }
                    inWord = false;
                default:
                    if (Character.isLetterOrDigit(c)) {
                        inWord = true;
                    }
            }
        }
        
        return count;
    }
    
    private static int countLinks(Document doc) {
        Elements links = doc.select("a[href]");
        return links.size();
    }
    
    private static int countImages(Document doc) {
        Elements images = doc.select("img[src]");
        return images.size();
    }
    
    private static int countInputFields(Document doc) {
        // we only count inputs of type text and textareas, as they account for
        // 99.9% of what we want
        Elements textInputs = doc.select("input[type=text]");
        Elements textareas = doc.select("textarea");
        return textInputs.size() + textareas.size();
    }
    
    /**
     * Format an Element to plain-text
     * @param element the root element to format
     * @return formatted text
     */
    public String getPlainText(Element element) {
        FormattingVisitor formatter = new FormattingVisitor();
        NodeTraversor traversor = new NodeTraversor(formatter);
        traversor.traverse(element); // walk the DOM, and call .head() and .tail() for each node

        return formatter.toString();
    }

    // the formatting rules, implemented in a breadth-first DOM traverse
    private class FormattingVisitor implements NodeVisitor {
        private static final int maxWidth = 80;
        private int width = 0;
        private StringBuilder accum = new StringBuilder(); // holds the accumulated text

        // hit when the node is first seen
        public void head(Node node, int depth) {
            String name = node.nodeName();
            if (node instanceof TextNode)
                append(((TextNode) node).text()); // TextNodes carry all user-readable text in the DOM.
        }

        // hit when all of the node's children (if any) have been visited
        public void tail(Node node, int depth) {
            String name = node.nodeName();
            if (name.equals("br"))
                append("\n");
            else if (StringUtil.in(name, "p", "h1", "h2", "h3", "h4", "h5"))
                append("\n\n");
        }

        // appends text to the string builder with a simple word wrap method
        private void append(String text) {
            accum.append(text + " ");
        }

        public String toString() {
            return accum.toString();
        }
    }
}
```


----------



## kevla (26. Okt 2013)

Ok der Programmierer hat mir jetzt die Quelle und das was er geaendert hat bei Github geschickt, oben das geaenderte (gruen ist hinzugefuegt, rot geloescht) und unten das original, vielleicht kann ja jemand mehr damit anfangen, warum er da einzelne Zeilen des Originals geaendert hat und wofuer das das Original eigentlich gedacht war. Er ueberschaetzt mich da mit meinem Javawissen.

Das ist der Link mit den zwei unterschiedlichen Versionen:

https://gist.github.com/SonOfLilit/ad9d10dddcf05a25d18d/revisions


----------



## ARadauer (26. Okt 2013)

Also du hast dir für ein Projekt die Lösung programmieren lassen und verstehst sie nun nicht.
Und wir sollen dir das erklären?


----------



## kevla (27. Okt 2013)

Ja Ist das nicht moeglich, einige Kommentare zu den Textzeilen zu schreiben, was diese bedeuten?  Ich dachte fuer jemanden der etwas von Java versteht, ist das schnell gemacht, der Programmcode war auch innerhalb weniger Stunden geschrieben, sonst entschuldigt, wenn ich zu viel verlange, aber ich bin ueber dem Code wirklich am verzweifeln.


----------



## MrClave (27. Okt 2013)

Ich denke, dass hier niemand sowas unterstützen wird.

Wieso hast du den Code nicht selbst geschrieben ?
Seid ihr noch nicht so weit in der Schule, oder wie können wir das verstehen, dass du andere hast arbeiten lassen für dein Projekt ?


----------



## dhalsim (27. Okt 2013)

Phase 3 ... opcorn:


----------



## kevla (27. Okt 2013)

Da kann ich direkt mit den letzten Teilen meiner Lebensgeschichte anfangen, wenn die Hintergruende interessieren. Ich studiere Informationsmanagement, bin im letzten Semester, es gibt allerdings diesen einen Kurs in dem ich dieser Javagruppe zugeteilt wurde, obwohl es direkt bei grundlegendem bei mir hakt und es wird bereits so etwas komplexes verlangt. Ok, ich kann verstehen, dass in diesem Forum insbesondere Javainteressierte sind, ich moechte spaeter allerdings nicht in diesem Bereich arbeiten und bin nicht der Programmiertyp, ich wollte aufgrund dieser Programmieranteile im Studium jetzt bereits abbrechen, da ich allerdings im letzten Semester bin und es auch weitreichend andere Gebiete im Studium gibt, moechte ich das Studium jetzt auch nicht hinwerfen. Ich versuche ja zu verstehen und habe auch neben meinem befreundeten Programmierer gesessen, welcher mir auch waehrenddessen versucht hat zu erklaeren, wie alles umgesetzt wird - allerdings hat dieser natuerlich auch nur begrenzt Zeit gehabt und mich auch in meinem Wissen ueberschaetzt, jetzt stolpere ich ueber meine Notizen und merke, dass ich damit nicht mehr wirklich etwas anfangen kann und wollte hier nur jemanden aus diesem Bereich bitten, wenn es keine grosse Aufgabe ist, mein Bekannter meinte auch, dass man es als Javaneuling entschluesseln koennte, was ich bezweifle, aber wenn man in dem Thema ist, koennte ich es mir vorstellen. Das war es auch schon..


----------



## dhalsim (27. Okt 2013)

... und Phase 4 opcorn:


----------



## kevla (28. Okt 2013)

Also weiss  irgendjemand vielleicht etwas bitte?!:/


----------



## KSG9|sebastian (28. Okt 2013)

Wann Phase 5 wohl startet? Heute Abend, oder doch erst morgen?


----------



## Ruzmanz (28. Okt 2013)

Du musst dich auch mal in unsere Situation versetzen. Nehmen wir mal an, dass du das Studium aufgrund unserer Hilfe schaffst, dann müssten wir vielleicht eines Tages mit dir im IT-Bereich arbeiten :bloed:

Jeder Java-Anfänger könnte deine Aufgabe lösen, dafür hättest du dich nicht in 2 Foren anmelden müssen ...


----------



## kevla (29. Okt 2013)

Das ist mein Problem, ich moechte nicht in der Java Branche arbeiten, ich muss nur dieses Projekt absolvieren um dann andere Sachen machen zu koennen und wenn die Umsetzung so einfach ist, dann dachte ich, kann ich von Experten die Hilfe bekommen, ich kenne keine privat keine Javaler, deswegen die Anmeldung.


----------



## ARadauer (29. Okt 2013)

kevla hat gesagt.:


> ich kenne keine privat keine Javaler


Studienkollegen?


----------



## kevla (29. Okt 2013)

nope, die koennen alle auch kein java, sonst haette ich schon wen gefragt, deswegen schreibe ich ja hier. Versuche jetzt noch ein englisches Forum, geldmaessig siehts auch knapp aus, n zehner koennte ich hoechstens investieren


----------



## ARadauer (29. Okt 2013)

zehner für was? dass ich dir beschreibe was der code macht? das bringt dir ja sowieso nix, das wirst du trotzdem nicht verstehen.

Hast du konkrete fragen zu dem code?


----------



## kevla (29. Okt 2013)

Hm ich dachte ich koennte es dann verstehen - die 3 Zeilen, die schon jemand kommentiert hatte, verstand ich dann ja auch:


```
private static int countLinks(Document doc) { // Zählt die Links
        Elements links = doc.select("a[href]"); // Holt alle Links aus dem Document
        return links.size(); // Gibt zurück, wie viele es sind
    }
```

Spezielle Fragen, die ich jetzt direkt haette waeren zB, was passiert, wenn eine Webseite nicht index.html heisst, die erkennt der Code dann nicht? Oder er hat auch spezielle Zeilen eingefuegt, wie das vorgefertigte Tool besser parst, also dass zum Beispiel keine einzelnen Zeichen oder Buchstaben als Wort gezaehlt werden, aber welche Zeilen das waren habe ich vergessen. Und wie genau sucht dieser Code nach Bildern, ich denke mich zu erinnern, dass er mehr tut, als nur nach dem img tag zu suchen, so hat er mir gesagt, so sollten Buttons zum Beispiel nicht als Bild gelten, aber auch da weiss ich nicht mehr wo genau dies gemacht wird. Und Inputfields, da bezieht er sich nur auf Searchboxes und Sachen, bei denen man etwas eingeben kann, oder noch etwas? Also wenn dort paar Kommentare neben den Zeilen stuenden, koennte ich diese Fragen zum Beispiel schon mal beantworten


----------

