Загрузка веб-страницы. ОК с wget, сбой с java

Я пытаюсь загрузить следующую страницу: http://structureddata.wikispaces.com/Test

wget без каких-либо опций не работает:

wget "http://structureddata.wikispaces.com/Test"
(...) connect to session.wikispaces.com insecurely, use `--no-check-certificate'

с --no-check-certificate работает

wget --no-check-certificate "http://structureddata.wikispaces.com/Test"
grep Hello Test
 Hello World

Теперь я хотел бы загрузить тот же URL-адрес с java, но следующую простую программу:

import java.net.*;
import java.io.*;
public class Test
        {
        public static void main(String args[])
                {
                int c;
                try
                        {
                        InputStream in=new URL("http://structureddata.wikispaces.com/Test").openStream();
                        while((c=in.read())!=-1) System.out.print((char)c);
                        in.close();
                        }
                catch(Throwable err)
                        {
                        err.printStackTrace();
                        }
                }
        }

ничего не возвращает

что мне сделать, чтобы загрузить страницу с java?

Большое спасибо,

Пьер


person Pierre    schedule 03.09.2010    source источник
comment
Есть что-то странное: ошибка указывает на то, что вы используете https, что не соответствует указанному URL-адресу. Я не могу воспроизвести сообщение от wget. Задействован ли прокси-сервер?   -  person Peter Tillemans    schedule 03.09.2010


Ответы (3)


Интерфейс Java URL довольно низкоуровневый; он не делает автоматически такие вещи, как следующие перенаправления. Ваш код выше не получает содержимого для печати, потому что его нет.

Сделав что-то вроде приведенного ниже, вы увидите, что получаете ответ HTTP 302 — перенаправление.

  URL url = new URL("http://structureddata.wikispaces.com/Test");

  URLConnection urlConnection = url.openConnection();
  Map<String, List<String>> headers = urlConnection.getHeaderFields();
  Set<Map.Entry<String, List<String>>> entrySet = headers.entrySet();
  for (Map.Entry<String, List<String>> entry : entrySet) {
    String headerName = entry.getKey();
    System.out.println("Header Name:" + headerName);
    List<String> headerValues = entry.getValue();
    for (String value : headerValues) {
      System.out.print("Header value:" + value);
    }
    System.out.println();
    System.out.println();
  }

Я бы предложил использовать библиотеку типа HTTPClient, которая будет обрабатывать больше протокола для ты.

(Спасибо, где это необходимо: скопирован приведенный выше код из здесь. )

person Dave Costa    schedule 03.09.2010
comment
Он автоматически следует редиректам, но не в том случае, если это касается другой схемы. Проверьте себя по ((HttpURLConnection) urlConnection).getFollowRedirects(). - person BalusC; 03.09.2010

Вы можете посмотреть на http://hc.apache.org/httpclient-3.x/tutorial.html, этот код возвращает страница без проблем

final HttpClient client = new HttpClient();
final GetMethod method = new GetMethod("http://structureddata.wikispaces.com/Test");
try {
    if (HttpStatus.SC_OK == client.executeMethod(method)) {
        System.out.println(IOUtils.toString(method.getResponseBodyAsStream()));
    } else {
        throw new IOException("Unable to load page, error " + method.getStatusLine());
    }
} finally {
    method.releaseConnection();
}
person Jon Freedman    schedule 03.09.2010

Проблема в том, что он возвращает ответ перенаправления 302 на URL-адрес https. Поскольку первоначальный запрос — http, а цель — https, URLConnection не будет автоматически следовать перенаправлению (однако это произойдет, если цель использует ту же схему).

После некоторого наблюдения я пришел к выводу, что он переходит к https для запроса токена аутентификации, который, в свою очередь, снова перенаправляется на URL-адрес http с токеном аутентификации в качестве параметра запроса. Таким образом, должны быть следующие перенаправления с http на https, а затем http с фактическим содержимым страницы.

Здесь работает следующее.

public static void main(String... args) throws Exception {
    // First request.
    URLConnection connection = new URL("http://structureddata.wikispaces.com/Test").openConnection();

    // Go to the redirected https page to obtain authentication token.
    connection = new URL(connection.getHeaderField("location")).openConnection();

    // Re-request the http page with the authentication token.
    connection = new URL(connection.getHeaderField("location")).openConnection();

    // Show page.
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
        for (String line; ((line = reader.readLine()) != null);) {
            System.out.println(line);
        }
    } finally {
        if (reader != null) try { reader.close(); } catch (IOException ignore) {}
    }
}

Однако я согласен с тем, что Commons HttpComponents Client является лучшим инструментом для работы.

person BalusC    schedule 03.09.2010