java - webapplicationexception - server returned http status 403
403 ¿Prohibido con Java pero no navegador web? (4)
Estoy escribiendo un pequeño programa de Java para obtener la cantidad de resultados para un término de búsqueda de Google determinado. Por alguna razón, en Java recibo un 403 Forbidden pero obtengo los resultados correctos en los navegadores web. Código:
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;
}
}
Y el error:
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)
¿Por qué está haciendo esto?
Es porque el sitio usa SSL. Intenta usar Jersey HTTP Client. Probablemente también tenga que aprender un poco sobre HTTPS y los certificados, pero creo que Jersey puede apostar configurado para ignorar la mayoría de los detalles relacionados con la seguridad real.
Para mí funcionó al agregar el encabezado: "Aceptar": "* / *"
Probablemente no estés configurando los encabezados correctos. Use LiveHttpHeaders
(o su equivalente) en el navegador para ver qué encabezados está enviando el navegador, luego emúlelos en su código.
Solo necesita configurar el encabezado del agente de usuario para que funcione:
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());
El SSL se manejó de forma transparente para usted, como se puede ver en su pila de excepción.
Sin embargo, obtener el monto del resultado no es tan simple, después de esto tienes que fingir que eres un navegador buscando la cookie y analizando el enlace del token de redirección.
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;
}
}
Ejecutando el código completo obtengo 2930000000L
como resultado.