2012-12-02 21 views
37

Ich schreibe ein kleines Java-Programm, um die Anzahl der Ergebnisse für einen bestimmten Google-Suchbegriff zu erhalten. Aus irgendeinem Grund bekomme ich in Java eine 403 verboten, aber ich bekomme die richtigen Ergebnisse in Webbrowsern. Code:403 Verboten mit Java aber nicht Webbrowser?

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.URL; 


public class DataGetter { 

    public static void main(String[] args) throws IOException { 
     getResultAmount("test"); 
    } 

    private static int getResultAmount(String query) throws IOException { 
     BufferedReader r = new BufferedReader(new InputStreamReader(new URL("https://www.google.com/search?q=" + query).openConnection() 
       .getInputStream())); 
     String line; 
     String src = ""; 
     while ((line = r.readLine()) != null) { 
      src += line; 
     } 
     System.out.println(src); 
     return 1; 
    } 

} 

Und der Fehler:

Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.google.com/search?q=test 
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source) 
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source) 
    at DataGetter.getResultAmount(DataGetter.java:15) 
    at DataGetter.main(DataGetter.java:10) 

Warum ist es dies zu tun?

+0

könnte etwas mit Sitzungen zu tun haben? – kishu27

+0

Warum verwenden Sie den SSL-Endpunkt? – Perception

+0

@Perception um ... was ist ein SSL-Endpunkt? (Entschuldigung, ich habe keine Ahnung von dieser Art von Sachen) – Doorknob

Antwort

68

Sie müssen nur User-Agent-Header setzen, damit es funktioniert:

URLConnection connection = new URL("https://www.google.com/search?q=" + query).openConnection(); 
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11"); 
connection.connect(); 

BufferedReader r = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8"))); 

StringBuilder sb = new StringBuilder(); 
String line; 
while ((line = r.readLine()) != null) { 
    sb.append(line); 
} 
System.out.println(sb.toString()); 

Die SSL transparent für Sie behandelt wurde, wie könnte aus Ihrer Ausnahme Stacktrace zu sehen.

Das Erhalten der Ergebnismenge ist nicht wirklich so einfach, danach müssen Sie fälschen, dass Sie ein Browser sind, indem Sie den Cookie holen und den Redirect-Token-Link analysieren.

String cookie = connection.getHeaderField("Set-Cookie").split(";")[0]; 
Pattern pattern = Pattern.compile("content=\\\"0;url=(.*?)\\\""); 
Matcher m = pattern.matcher(response); 
if(m.find()) { 
    String url = m.group(1); 
    connection = new URL(url).openConnection(); 
    connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11"); 
    connection.setRequestProperty("Cookie", cookie); 
    connection.connect(); 
    r = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8"))); 
    sb = new StringBuilder(); 
    while ((line = r.readLine()) != null) { 
     sb.append(line); 
    } 
    response = sb.toString(); 
    pattern = Pattern.compile("<div id=\"resultStats\">About ([0-9,]+) results</div>"); 
    m = pattern.matcher(response); 
    if(m.find()) { 
     long amount = Long.parseLong(m.group(1).replaceAll(",", "")); 
     return amount; 
    } 

} 

the full code Laufen ich 2930000000L als Ergebnis.

+0

Alter, ich schulde dir ein Fass Bier, das ist so eine perfekte Lösung für mein Problem! Kann Google Ihre Ergebnisse mit dieser Methode einschränken/drosseln? – gudthing

+0

@Gudthing Drosselung ist IP-basiert, es geht also nicht um die Methode, aber ob Sie Ihre IP ändern :-) – Esailija

+0

Ich sehe! Ein einfacher Router-Neustart (für WAN-Änderung) wird das Problem lösen :). Danke noch einmal!! – gudthing

1

Wahrscheinlich setzen Sie nicht die richtigen Header. Verwenden Sie LiveHttpHeaders (oder gleichwertig) im Browser, um zu sehen, welche Header der Browser sendet, und emulieren Sie sie dann in Ihrem Code.

+0

Ich versuchte '" https://www.google.com/search?q= "+ query +" & rlz = 1C1RNNN_enUS371 & aq = f & oq = "+ Abfrage +" & sugexp = chrome, mod = 6 & sourceID = chrome & ie = UTF-8 "' , immer noch nicht funktioniert – Doorknob

+0

@PicklishDoornknob Sie einen Query-String-Parameter hinzugefügt, haben Sie nicht die Header geändert. Sie können Header mit '.setRequestProperty()' auf dem 'URLConnection' -Objekt setzen. – Esailija

+0

Hier ist ein SO-Artikel, der über das Hinzufügen von Anforderungsheadern spricht: http://stackoverflow.com/questions/480153/how-to-modify-the-header -of-a-httpurlconnection –

0

Es ist weil die Seite SSL verwendet. Versuchen Sie es mit dem Jersey HTTP Client. Sie werden wahrscheinlich auch etwas über HTTPS und die Zertifikate lernen müssen, aber ich denke, dass Jersey darauf setzen kann, die meisten Details bezüglich der tatsächlichen Sicherheit zu ignorieren.

+1

Nein ist es nicht, es funktioniert nur durch emulieren Browser HTTP-Header wie @KevinDay sagte in seiner Antwort. – Esailija

+2

@Ben Brunk - hier gibt es eine gute Lektion - im Kern besteht die gesamte Programmierung aus Schicht einer Schicht zusätzlicher Abstraktion. Das Verständnis der niedrigen Stufe ist sehr nützlich. Die Verwendung eines Clients auf höherer Ebene, wie Sie es beschreiben, könnte funktionieren - aber nur, weil Sie einen Anruf auf niedriger Ebene durchführen, den Sie selbst erstellen könnten, wenn Sie dies wünschen. Ich werde nie vergessen, wie aufschlussreich es war, dass ich mich hinsetzte und mit einem Webserver über einen Telnet-Client interagierte und die HTTP-Anfrage von Hand erstellte. Cheerio! –

+0

Eigentlich bin ich mir immer noch nicht sicher, warum dieser Code funktioniert, weil Sie normalerweise das öffentliche Zertifikat der Site zu Ihrem lokalen Java-Keystore hinzufügen müssen, um SSL, auch mit URLConnection, zu verwenden, damit sich etwas über diese URL nicht aufaddiert . Was lässt Sie glauben, dass ich nie eine Telnet-Verbindung zu einer Website hergestellt habe? Ich mache das für meinen Lebensunterhalt und ich vergesse oft, dass es viele Leute auf dieser Seite gibt, die Studenten oder Hobby-Programmierer sind. Ich versuche nur, hepeful zu sein. –

Verwandte Themen