# Mit "Java" html-Seite entscripten



## Kruzgoth (5. Aug 2011)

Hallo Leute,

hab da ein kleines Problemchen.
Hab im Anhang meinen Code für ein kleines Projekt von mir hochgeladen
und hab da ein paar Probleme.
Und zwar, soll das Programm den Code von einer Html runterladen, von allen Html-Codes und anderen
Scripts entfernen und den reinen Text anzeigen, der auch auf der Seite sichtbar steht.

So.

Schritt 1. und 2. klappen bei mir schon ganz gut, wird runtergeladen und auch schon grob gefiltert,
sodass nur noch einzelne Scripts innerhalb der Texte vorhande sind,
für z.B. *Fett markierung* oder _Kursiv_ und auch ein paar für Links mit "<a href=*** bla>

Mein Problem ist, dass ich es nicht schaffe, die Scripts sauber von dem reinen Text zu löschen, ohne
einen großteil des Textes zu löschen.
Könntet ihr mir da bitte helfen? Der regt mich schon seit Tagen auf. -.-

Bei mir die Seite als Testobjekt ist: Tomburg ? Wikipedia
Mein Problem fängt an ab Zeile 107 
[JAVA=107]Pattern p1 = Pattern.compile("\\<p\\>");
		Pattern tre = Pattern.compile("<a href=.+>");
		i=0;
		boolean in;
		while(i<laenge)
		{
			pruf = true;
			while(pruf ==true)
			{			
				in = false;
				Matcher p = p1.matcher(inhalt_);
				Matcher test = tre.matcher(inhalt);
				if(p.find()==true)
				{
					inhalt = inhalt.substring(0,p.start()) + inhalt.substring(p.end());

					in = true;
				}
				if(test.find()==true)
				{
					inhalt = inhalt.substring(0, test.start()) + inhalt.substring(test.end()-3);
					in = true;
				}

				if(in == false)
				pruf = false;
			}
			i++;
		}

		for(i=0;i<laenge;i++)
		{
			System.out.println(inhalt);
		}

	}[/code]

Bitte helft mir!!_


----------



## Matthias K. (5. Aug 2011)

Hi Kruzgoth,
ich würde einfach das Dokument einlesen und in einen String zwischenspeichern.
Darauf den String in ein Char-Array umwandeln und einen anderen String mit jedem Zeichen
des Arrays "addieren". Dabei sollte aber überprüft werden, ob es sich bei dem aktuellen 
Zeichen (char) um eine "<" handelt. Falls dies der Fall ist, setzt du einfach 
eine lokale boolean auf true und erst wieder auf false, wenn ein anderes Zeichen ">"enthählt.
Ist diese boolean true, wird das aktuelle Zeichen einfach nicht mehr an den String angehängt
und du erhältst einen String ohne jegliche "< Befehl >".
Wende dieses Beispiel einfach auf alle anderen Merkmale, wenn notwendig, sogar auf ganze 
Befehle an und du erhältst einen reinen String.

Gruß,
Matthias


----------



## nillehammer (5. Aug 2011)

> ich würde einfach das Dokument einlesen und in einen String zwischenspeichern.


Genau, bis hierhin, wie von Matthias K. vorgeschlagen. Dann das hier:

```
final String htmlStr = "<head><title>Seitentitel</title></head><body>"
				+ "<h1 class=\"error\">Seitenüberschrift</h1><p class=\"content\">Seitentext</p></body>";

		System.out.println("***Originaltext***");
		System.out.println(htmlStr);

		final String noOpeningTags = htmlStr.replaceAll("<[^/].+?>", "");

		System.out.println("***Öffnende Tags entfernt***");
		System.out.println(noOpeningTags);

		final String closingTagsToLineBreaks = noOpeningTags.replaceAll("</.+?>",
				System.getProperty("line.separator"));

		System.out.println("***Schließende Tags in Zeilenumbrüche umgewandelt***");
		System.out.println(closingTagsToLineBreaks);
```

In dem Code habe ich String.replaceAll benutzt. Du kannst aus den Regex-Strings vorher natürlich auf Patterns compilieren und dann das hier machen:

```
...
final Pattern openingPattern = Pattern.compile("<[^/].+?>");

final String noOpeningTags = openingPattern.matcher(htmlStr).replaceAll("");
...
```


----------



## anonym (5. Aug 2011)

Also, ich würde eine library wie htmlparser (HTML Parser - HTML Parser) verwenden. Damit kriege ich eine Darstellung der Baumstruktur des Dokuments, in der ich entschlüsseln kann, welcher tag was ist. Anschließend implementierst du mit dem NodeVisitor, den die Bib anbietet einen Lauf über alle Nodes und sammelst die Sachen ein, die du haben willst.


----------



## nillehammer (6. Aug 2011)

> Also, ich würde eine library wie htmlparser (HTML Parser - HTML Parser) verwenden.


anonym hat Recht. Wenn es hier darum geht, anhand eines Beispiels mit Praxisbezug Regex zu üben ist das in Ordnung. Ansonsten ist auf lange Sicht eine geeigente Library selbst programmiertem Code immer vorzuziehen. Wobei wir dann bei der Schwierigkeit wären, zu erkennen, ob eine Library "geeignet" ist...:rtfm:


----------



## RySa (6. Aug 2011)

Also ich würd gerne wissen, was du als Text bezeichnest. Zählt zum Beispiel <a href=...> text </a> , dieser "text" auch als Text ? also ich nehme an, der Text ist sowieso immer ausserhalb der Klammern eckigen Klammern. Falls du unbedingt Regex benutzen willst, dann vielleicht so etwas (um zumindest die eckigen Klammern zu "entfernen" und den reinen Text rauszuholen:

```
public static void main(String[] args) {
		String s = "der HTML Inhalt";
		Pattern pattern = Pattern.compile("<.*?>(.*?)<.*?>");
		Matcher matcher = pattern.matcher(s);
		
		while (matcher.find()){
			System.out.println(matcher.group(1));
		}

	}
```

Warum es bei dir mit 

```
Pattern tre = Pattern.compile("<a href=.+>");
```
nicht klappt, das kann ich dir sagen. .+ (ein greedy quantifier) heißt ja beliebiges zeichen einmal oder mehrmals. Nun zählt zu den "beliebigen Zeichen" auch das >, somit wird das .+ alles "fressen" bis er das letzte > trifft. In solchen Fällen solltest du .+? (relucant quantifier)benutzen, der "aufpasst" ob da nicht schon auf dem weg ein die Zeichenkette vorkommt, die hinter ihm steht, also in deinem Fall >.


Anonsten würde ich auf jeden Fall einen HTML bzw. XML Parser benutzen, mit dem du ganz leicht dir nur denn reinen angezeigten Text speichern/ausgeben kannst


----------



## Kruzgoth (16. Aug 2011)

Danke leute,
hab es soweit hingekriegt, auch samt von mir gewünschten Erweiterungen.
Hab dazu überwiegend einfach mal Pattern und Matcher verwendet, weil mir anderes nicht
so geläufig war, trotzdem danke für die reichen Antworten ^^

Stell euch mal kurz den Source rein, womit ich alles Filter, was ich haben wollte ^^, sowie diese doofen Sonderzeichen-ersetzung =)


```
public static String[] filter (String[] temp)
	{	int i = 0;
		String[] clone = temp.clone();
		Pattern eins = Pattern.compile("\\<\\!");
		Pattern zwei = Pattern.compile("\\>");
		Pattern drei = Pattern.compile("\\<script\\>");
		Pattern vier = Pattern.compile("\\<noscript\\>");
		Pattern fuenf = Pattern.compile("\\<\\/(.+)?script\\>");
		Pattern sechs = Pattern.compile("\\<style(.+)?\\>");
		Pattern sieben = Pattern.compile("\\<\\/style\\>");
		Pattern fk2 = Pattern.compile("\\<script.+language\\=\"javascript");
		Pattern fk = Pattern.compile("\\<script.+type\\=(\"|\')text\\/javascript");
		for(i=0;i>temp.length;i++)
			clone[i] = clone[i].trim();	//Löschen von "Free-space"
		
		boolean pruf;
		i=0;
		while(i < temp.length)
		{
			Matcher se = sechs.matcher("");
			Matcher si = sieben.matcher("");
			Matcher fu = fuenf.matcher("");
			Matcher ei = eins.matcher("");
			Matcher zw = zwei.matcher("");
			pruf = true;
			Matcher f = fk.matcher(clone[i].toLowerCase(Locale.GERMAN));
			Matcher f2 = fk2.matcher(clone[i].toLowerCase(Locale.GERMAN));
			Matcher dr = drei.matcher(clone[i].toLowerCase(Locale.GERMAN));
			Matcher vi = vier.matcher(clone[i].toLowerCase(Locale.GERMAN));
			//Abfrage, ob ein "<script?> gefunden wurde, egal welcher art,ob <script> oder <noscript>
			//oder ob irgendein "<script type=text/javascript..>" oder "<script language...>" gefunden wurde
			if(f.find()==true || f2.find()==true  || vi.find()==true || dr.find()==true)
			{
				pruf = true;
				while(pruf == true)
				{
					if(i>=temp.length)	//Abbrechschleife, IST notwendig!(intern)
					{
						pruf = false;
						break;
					}
					f2 = fk2.matcher(clone[i].toLowerCase(Locale.GERMAN));	//Generieren der Matcher auf die passende Zeile
					if(f2.find()==true)	//Prüfen, ist "<script language...>" im text?
					{
						clone[i] = clone[i].substring(f2.end());
					}
					dr = drei.matcher(clone[i].toLowerCase(Locale.GERMAN));//Generieren der Matcher auf die passende Zeile	
					if(dr.find()==true)	//Prüfen, ist "<script>" im text?
					{
						clone[i] = clone[i].substring(dr.end());
					}
					vi = vier.matcher(clone[i].toLowerCase(Locale.GERMAN));//Generieren der Matcher auf die passende Zeile
					if(vi.find()==true)	//Prüfen ist "<noscript>" im text?
					{
						clone[i] = clone[i].substring(vi.end());
					}
					f = fk.matcher(clone[i].toLowerCase(Locale.GERMAN));	//Generieren der Matcher auf die passende Zeile
					if(f.find()==true)	//Prüfen ist "<script type=....>" im text?
					{
						clone[i] = clone[i].substring(f.end());
					}
					//Abbruch bedingungen für die Schleife
					fu = fuenf.matcher(clone[i].toLowerCase(Locale.GERMAN));
					dr = drei.matcher(clone[i].toLowerCase(Locale.GERMAN));	//Generieren der Matcher auf die passende Zeile
					//Wenn "</script>" gefunden wird UND "<script>"
					if(fu.find()==true && dr.find(fu.start())==true)
					{
						clone[i] = clone[i].substring(dr.end());
					}	//dann geht die Schleife einfach weiter
					fu = fuenf.matcher(clone[i].toLowerCase(Locale.GERMAN));	//Generieren der Matcher auf die passende Zeile
					if(fu.find()==true)	//Falls NUR "</script>" gefunden wird
					{
						clone[i] = clone[i].substring(fu.end());							
						pruf = false;	//Beendigung der Schleife
					}
					else	//Falls das Ende nicht erreicht ist, Zeile löschen
					{
						clone[i] = "";
					}
					//Schleife zur abfrage, ob was gefunden wurde,
					//wenn was gefunden wurde, wird dieselbe Zeile nochmals geprüft
					if(pruf == true)	
					i++;
				}
			}
			//gleiches System wie oben drüber, allerdings nur mit 1 anfangs und 1 end variablen
			if(i<temp.length)
				se = sechs.matcher(clone[i].toLowerCase(Locale.GERMAN));
				if(se.find()==true)
				{
					pruf = true;
					while(pruf == true)
					{
						if(i>=temp.length)
						{
							pruf = false;
							break;
						}
						si = sieben.matcher(clone[i].toLowerCase(Locale.GERMAN));
						if(si.find()==true)	//Falls ende gefunden, beenden
						{
							clone[i] = clone[i].substring(si.end());
							pruf = false;
						}
						else if(si.find()==false)	//Ansonsten Zeile = leer und weiter
						{
							clone[i] = "";
						}
						if(pruf == true)//Solange was gefunden, selbe Zeile
						i++;
					}
				}
			if(i<temp.length)	//Selbe prinzip wie oben drüber
			ei = eins.matcher(clone[i].toLowerCase(Locale.GERMAN));	//sucht nach "<!" ausdrücken
			if(ei.find()==true)
			{
				pruf = true;
				while(pruf == true)
				{
					if(i>=temp.length)
					{
						pruf = false;
						break;
					}
					zw = zwei.matcher(clone[i].toLowerCase(Locale.GERMAN));	//sucht nach ">" ausdrücken
					if(zw.find()==true)
					{
						clone[i] = "";
						pruf = false;
					}
					else if(zw.find()==false)
					{
						clone[i] = "";
					}
					if(pruf == true)
					i++;
				}
			}
			if(pruf == true)	//Allgemeine Abfrage, ob irgendwas gefunden wurde
				i++;
		}
		
		clone = rausschneiden(clone);
		clone = ersetzen(clone);	//Letzten Feinschliffe
		
		for(i = 0;i<clone.length;i++)
		{
			clone[i] = clone[i].trim();
			if(clone[i].equals(""))
				clone[i]= null; 
		}
		
		temp = anpassen(clone);
		
		return temp;	//Rückgabe des Arrays
	}
	
	//Passt die Array-länge auf den Inhalt an
	//Passt die Array-länge an
	public static String[] anpassen(String[] inhalt)
	{
		int p = 0;	//Stellenvariablen für das Array
		int i;
		for(i=0;i<inhalt.length;i++)	//Schleife bis Arrayende
		{
			if(inhalt[i]!=null)		//wenn der inhalt nicht null ist
			{
				inhalt[p] = inhalt[i];	//setzen der Stelle i an die Stelle p
				if(p!=i)
				inhalt[i] = null;		//inhalt an der Stelle i löschen
				p++;					//Countervariable erhöhen
			}
		}
		String[] temp = inhalt.clone();	//Klonen des Inhaltes zur
		inhalt = new String[p];		//veränderung der Array-größe
		for(i=0;i<p;i++)	//und erneute übergabe der Werte in das neu-große Array
		{
			inhalt[i] = temp[i];	//Übernahme aller nicht-null Elementen (s.Z.136-141)
		}
		return inhalt;	//Rückgabe des neuen Inhaltes
	}

	//Schneidet restlichen Script raus
	//Funktion zum rausschneiden von Html-Code
	public static String[] rausschneiden(String[] inhalt)
	{
		boolean pruf;
		boolean in;
		boolean test;
		int start = 0;		//Stellenvariablen, "Zeichen" kommt an stelle x
		int end = 0;		//endet an stelle y...
		int i = 0;	//Zählvariable
		int laenge = inhalt.length;	//Übernahme der Zählvariable
		
		while(i<laenge)	//Solange Zählvariable nicht über Array-größe hinaus springt
		{
			pruf = true;//Zweifach verkettete Boolean-abfrage
						//zum Sicherstellen keiner Überschreibung und das alles
						//behandelt wurde
			while(pruf ==true)
			{			
				in = false;
					start = -1;
					end=-1;
					if(i<laenge)
					start = inhalt[i].indexOf("<", start);	//Start wird index gesetzt vom "Zeichen"
					if(start != -1)	//falls zeichen vorhanden
					{
						in = true;	//Setzen von "ist drin"variable = true
						end = inhalt[i].indexOf(">", start);	//end wird index gesetzt vom "zeichen2"
						if(end != -1)
						inhalt[i] = inhalt[i].substring(0,start) + inhalt[i].substring(end+1);	//Schneiden des Inhaltes angepasst an start und ende
						else if(end == -1)	//Weiterprüfung falls ende -1
						{
							test = true;
							while(test == true)	//solange kein ende in sicht
							{
								if(i>=laenge)
								{
									test = false;
									break;
								}
								//Wenn ende gefunden, abschneiden und abbrechen
								if((end = inhalt[i].indexOf(">"))!=-1)	
								{
									inhalt[i] = inhalt[i].substring(end+1);
									test = false;
								}
								else 	//falls nicht, einfach Zeile leeren
								{
									inhalt[i] = "";
								}
								if(test == true) //solange ende nicht gefunden, selbe Zeile
								i++;
							}
						}
					}
					start = -1;
					if(i<laenge)
					start = inhalt[i].indexOf("[",start);	//Wiederholung mit "neuem Zeichen"
					if(start != -1)	//Wenn start gefunden,dann
					{
						in = true;
						end = inhalt[i].indexOf("]",start);//ende suchen 
						if(end != -1)		//Falls ebenfalls gefunden
							inhalt[i] = inhalt[i].substring(0,start) + inhalt[i].substring(end+1);	//Schneiden des Inhaltes angepasst an start und ende
							else if(end == -1) //falls ende nicht gefunden, bis zum start schneiden und weitermachen
								inhalt[i] = inhalt[i].substring(0,start);
					}
					if(in == false)
						pruf = false;
			}
			i++;	//Zähler erhöhen (nächstes Element)
		}
		i = 0;
		while(i<inhalt.length)	//Löschschleife aller restlich verbliebenen Funktionsklammern
		{				//die z.b. mehrfach hintereinander auftauchen, Beispiel: "af9fh=73jif>>>"
			while((end = inhalt[i].indexOf(">"))!=-1)
		{
				if((start = inhalt[i].indexOf("<"))!= -1)
					inhalt[i] = inhalt[i].substring(end, start);
				else
			inhalt[i] = inhalt[i].substring(end+1);
		}
			i++;
		}
		return inhalt;	//Rückgabe des optimierten Arrays
	}

	//Funktion zum ersetzen von Sonderzeichen und ähnlichem
	public static String[] ersetzen(String[] inhalt)
		{
			int i = 0;
			int laenge = inhalt.length;
			while(i<laenge)	//Solange nicht über Array-länge springt
			{	
				//Ersetzen aller "komischen Zeichen" durch "besseres Zeichen"
					inhalt[i] = inhalt[i].replaceAll("Ã¤", "ä");
					inhalt[i] = inhalt[i].replaceAll("&auml;","ä");
					inhalt[i] = inhalt[i].replaceAll("Ã¼", "ü");
					inhalt[i] = inhalt[i].replaceAll("&uuml;", "ü");
					inhalt[i] = inhalt[i].replaceAll("Ãº", "ú");
					inhalt[i] = inhalt[i].replaceAll("Ã¶", "ö");
					inhalt[i] = inhalt[i].replaceAll("&ouml;", "ö");
					inhalt[i] = inhalt[i].replaceAll("ÃŸ", "ss");
					inhalt[i] = inhalt[i].replaceAll("&szlig;", "ss");
					inhalt[i] = inhalt[i].replaceAll("Ã„", "Ä");
					inhalt[i] = inhalt[i].replaceAll("â€ž", ",,");
					inhalt[i] = inhalt[i].replaceAll("&amp;", "&");
					inhalt[i] = inhalt[i].replaceAll("Â°", "°");
					inhalt[i] = inhalt[i].replaceAll("&copy;", "©");
					inhalt[i] = inhalt[i].replaceAll("&bull;","");
					inhalt[i] = inhalt[i].replaceAll("▼", "");
					inhalt[i] = inhalt[i].replaceAll("&deg", "°");
					inhalt[i] = inhalt[i].replaceAll("'", "`");
					inhalt[i] = inhalt[i].replaceAll(" ", " ");
					inhalt[i] = inhalt[i].replaceAll("â‚¬", "€");
					inhalt[i] = inhalt[i].replaceAll("&middot;", "·");
					inhalt[i] = inhalt[i].replaceAll("&trade;", "™");
					inhalt[i] = inhalt[i].replaceAll("â€œ", "\"");
					inhalt[i] = inhalt[i].replaceAll("&quot;", "\"");
					inhalt[i] = inhalt[i].replaceAll("&raquo;", ">>");
					inhalt[i] = inhalt[i].replaceAll("&nbsp;", " ");
					inhalt[i] = inhalt[i].replaceAll("&laquo;", "<<");
					inhalt[i] = inhalt[i].replaceAll("&lsaquo;", "<");
					inhalt[i] = inhalt[i].replaceAll("&rsaquo;", ">");
					inhalt[i] = inhalt[i].replaceAll("â€“", "-");
					inhalt[i] = inhalt[i].replaceAll("Ã–", "Ö");
					inhalt[i] = inhalt[i].replaceAll("Ã©", "é");
					inhalt[i] = inhalt[i].replaceAll("&Uuml;","Ü");
					inhalt[i] = inhalt[i].replaceAll("Ãœ", "Ü");
					inhalt[i] = inhalt[i].replaceAll("Â","");
				
				i++;	//Zähler erhöhen (nächstes Element)
			}
			return inhalt;
		}
```


----------

