Вопрос-ответ

403 Forbidden with Java but not web browser?

403 Запрещено с Java, но не в веб-браузере?

Я пишу небольшую Java-программу для получения количества результатов по заданному поисковому запросу Google. По какой-то причине в Java я получаю 403 Запрещено, но я получаю правильные результаты в веб-браузерах. Код:

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;
}

}

И ошибка:

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)

Почему он это делает?

Переведено автоматически
Ответ 1

Вам просто нужно установить заголовок пользовательского агента, чтобы он работал:

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());

Протокол SSL был прозрачно обработан для вас, как видно из вашего стека исключений.

Получить итоговую сумму на самом деле не так просто, после этого вам нужно притвориться, что вы браузер, извлекая файл cookie и анализируя ссылку на токен перенаправления.

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;
}

}

В результате выполнения полного кода я получаю 2930000000L.

Ответ 2

Для меня это сработало, добавив заголовок: "Accept": "* / *"

Ответ 3

Вероятно, вы устанавливаете неправильные заголовки. Используйте LiveHttpHeaders (или эквивалент) в браузере, чтобы увидеть, какие заголовки отправляет браузер, затем эмулируйте их в своем коде.

Ответ 4

Это потому, что сайт использует SSL. Попробуйте использовать HTTP-клиент Jersey. Вероятно, вам также придется немного узнать о HTTPS и сертификатах, но я думаю, что Jersey может сделать ставку на игнорирование большинства деталей, касающихся реальной безопасности.

java