# Kryptische Zeichen beim Auslesen einer Website



## Ganondorf (25. Feb 2010)

Hallo Leute

Ich habe Probleme eine Webseite auszulesen. Ich benutze denselben Codeschnipsel bei vielen Seiten und bei den meisten klappt er auch, aber bei einigen kommen nur komische Zeichen raus.

Mein Code:

```
URL url = new URL("http://anidb.net/perl-bin/animedb.pl?show=main");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
System.out.println(reader.readLine());
```

Das Ergebnis lässt sich hier nicht reinkopieren. Ich hoffe jemand kann mir helfen.

Mfg Ganondorf


----------



## Gast2 (25. Feb 2010)

Dann werden die Seiten wohl einen nicht UFT8/16 kompatiblen Zeichensatz verweden. Gibt doch mal die URL zu einer Seite die funktioniert und eine die nicht funktioniert.


----------



## Ganondorf (25. Feb 2010)

So was hab ich mir auch schon gedacht. Ich weiß aber nicht wie man nicht-UTF8/16-Webseiten ausliest. Eine Seite die funktioniert ist z.B. Google. Die Seite http://anidb.net/perl-bin/animedb.pl?show=main funktioniert nicht.


----------



## Gast2 (25. Feb 2010)

Du kannst den charset auslesen über den header, aber der BufferReader kann nur UTF8/16


```
URLConnection uc = url.openConnection();

		for (String key : uc.getHeaderFields().keySet()) {
                       // print all header fields
			System.out.println(uc.getHeaderFields().get(key));
		}
		String charset = uc.getContentType().split("charset=")[1];
		InputStreamReader input = new InputStreamReader(uc.getInputStream(),
				charset);
		StringBuilder buffer = new StringBuilder();
		int c;
		while ((c = input.read()) != -1) {
			buffer.append((char) c);
		}
		String str = buffer.toString();
		String[] zeilen = str.split("\n"); // oder \r\n je nach EOL Style
		for (String s : zeilen) {
			System.out.println(s);
		}
	}
```

Wenn du es somachst kannst du aber auch gleich der UrlConnection einen ContentTypeHandler geben.

Zu deiner Beispielseite - die spezifiziert sich selber als UTF8, aber was da rüber kommt ist es meiner Ansicht nach nicht


----------



## Ganondorf (25. Feb 2010)

Kann man irgendwie herausfinden, welches Charset die Webseite benutzt, ohne den Header zu benutzen? Da würde mir auch irgendein externes Programm reichen.


----------



## Gast2 (25. Feb 2010)

Nein, du kannst dann nur Bytepattern raten 

Hmm, ich denke das es bei der Seite nicht geht liegt daran das das PERL skript auf dem server nur Stuß sended wenn man nicht einen ordentlichen HTTP Request macht.

Du solltest dir evtl mal den HTTPClient ansehn:
HttpClient - HttpClient Tutorial


----------



## Ganondorf (25. Feb 2010)

Ich habs mit dem HttpClient versucht krieg da aber nix hin, egal welches Beispiel ich ausprobiere. Entweder er findet irgendeine Klasse nicht, oder wirft eine Exception. Ich habs jetzt mal mit Version 3.1 versucht aber, der findet immer die LogFactory nicht. Hast du irgendein funktionierendes Beispiel?


----------



## Gast2 (25. Feb 2010)

Wahahaha - jetzt fällt es mir wie Schuppen vor den Augen.

Die Seite schickt den Content gezippt...


```
String url = "http://anidb.net/perl-bin/animedb.pl?show=main";
	HttpClient httpclient = new DefaultHttpClient();
	HttpGet httpget = new HttpGet(url);
	HttpResponse response = httpclient.execute(httpget);
    for (Header h : response.getAllHeaders()){
    	System.err.println(h.getName() +" = "+h.getValue());
    }
```

Date = Thu, 25 Feb 2010 20:13:48 GMT
Server = Apache
Cache-control = no-cache
Pragma = no-cache
Content-Type = text/html; charset=UTF-8
Expires = Thu, 25 Feb 2010 20:13:48 GMT
Set-Cookie = adbuin=1267128828-qsjM; path=/; expires=Sun, 23-Feb-2020 20:13:48 GMT
Vary = Accept-Encoding
Content-Encoding = gzip
Keep-Alive = timeout=4, max=50
Connection = Keep-Alive
Transfer-Encoding = chunked



Da hilft dir dann soetwas:

```
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.HttpEntityWrapper;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

public class ClientGZipContentCompression {

    public final static void main(String[] args) throws Exception {
        DefaultHttpClient httpclient = new DefaultHttpClient();

        httpclient.addRequestInterceptor(new HttpRequestInterceptor() {
           
            public void process(
                    final HttpRequest request, 
                    final HttpContext context) throws HttpException, IOException {
                if (!request.containsHeader("Accept-Encoding")) {
                    request.addHeader("Accept-Encoding", "gzip");
                }
            }

        });
        
        httpclient.addResponseInterceptor(new HttpResponseInterceptor() {
           
            public void process(
                    final HttpResponse response, 
                    final HttpContext context) throws HttpException, IOException {
                HttpEntity entity = response.getEntity();
                Header ceheader = entity.getContentEncoding();
                if (ceheader != null) {
                    HeaderElement[] codecs = ceheader.getElements();
                    for (int i = 0; i < codecs.length; i++) {
                        if (codecs[i].getName().equalsIgnoreCase("gzip")) {
                            response.setEntity(
                                    new GzipDecompressingEntity(response.getEntity())); 
                            return;
                        }
                    }
                }
            }
            
        });
        
        HttpGet httpget = new HttpGet("http://anidb.net/perl-bin/animedb.pl?show=main"); 
        
        // Execute HTTP request
        System.out.println("executing request " + httpget.getURI());
        HttpResponse response = httpclient.execute(httpget);

        System.out.println("----------------------------------------");
        System.out.println(response.getStatusLine());
        System.out.println(response.getLastHeader("Content-Encoding"));
        System.out.println(response.getLastHeader("Content-Length"));
        System.out.println("----------------------------------------");

        HttpEntity entity = response.getEntity();
        
        if (entity != null) {
            String content = EntityUtils.toString(entity);
            System.out.println(content);
            System.out.println("----------------------------------------");
            System.out.println("Uncompressed size: "+content.length());
        }

        // When HttpClient instance is no longer needed, 
        // shut down the connection manager to ensure
        // immediate deallocation of all system resources
        httpclient.getConnectionManager().shutdown();        
    }

    static class GzipDecompressingEntity extends HttpEntityWrapper {

        public GzipDecompressingEntity(final HttpEntity entity) {
            super(entity);
        }
    
        @Override
        public InputStream getContent()
            throws IOException, IllegalStateException {

            // the wrapped entity's getContent() decides about repeatability
            InputStream wrappedin = wrappedEntity.getContent();

            return new GZIPInputStream(wrappedin);
        }

        @Override
        public long getContentLength() {
            // length of ungzipped content is not known
            return -1;
        }

    } 
    
}
```

Du musst als libs haben:

commons-logging-1.1.1
httpclient-4.0.1
httpmime-4.0.1
httpcore-4.0.1

Kannst auch versuchen den einfach auf den ganz naiven Weg wie in deinem ersten Posting den Content zu holen und dann zu entpacken:

```
public static String unzipStringFromBytes( byte[] bytes ) throws IOException
	  {
	    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
	    BufferedInputStream bufis = new BufferedInputStream(new GZIPInputStream(bis));
	    ByteArrayOutputStream bos = new ByteArrayOutputStream();
	    byte[] buf = new byte[1024];
	    int len;
	    while( (len = bufis.read(buf)) > 0 )
	    {
	      bos.write(buf, 0, len);
	    }
	    String retval = bos.toString();
	    bis.close();
	    bufis.close();
	    bos.close();
	    return retval;
	  }
```


----------



## Ganondorf (25. Feb 2010)

Super, die erste Methode funktioniert. Aber womit genau müsste ich die zweite Methode füttern? Ist das die Ausgabe des InputStreamReaders als Byte-Array, oder was?


----------



## Gast2 (25. Feb 2010)

Ganondorf hat gesagt.:


> Ist das die Ausgabe des InputStreamReaders als Byte-Array, oder was?



Ja, sollte auch gehen - am besten halt auch einen ByteArrayInputStream als input nehmen.


----------



## HoaX (25. Feb 2010)

hab nix gesagt


----------



## Ganondorf (25. Feb 2010)

@Hoax:
Was sollte der Kommentar?

@fassy:
Wie komme ich genau von einer Webadresse denn am besten an dieses byte-Array?

Und noch was zu der ersten Methode, wenn ich eine "Corrupt GZIP trailer"-Exception krieg, liegt das an der Webseite oder am Programm?


----------

