Не удается получить XML из веб-страницы в строку на Java

#java #xml #http

Вопрос:

У меня проблема с получением XML с этой веб-страницы. В браузере он отображается правильно, и проблем нет, но когда дело доходит до Java, все по-другому.

Я попробовал два метода, оба из которых привели к исключению.

 // Method 1 - Using Java's URL
URL url = new URL(/* mentioned link */);
String rawXML = new String(url.openStream().readAllBytes(), StandardCharsets.UTF_8); // java.io.IOException: Invalid Http response
 
 // Method 2 - Using Apache's HTTP client
HttpGet httpGet = new HttpGet(/* mentioned link */);
String rawXML = EntityUtils.toString(HttpClients.createDefault().execute(httpGet).getEntity()); // org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response
 

Загрузка этой веб-страницы с wget помощью аргумента --content-on-error работает, но она ненадежна, так как wget не всегда доступен во всех системах, таких как Windows.

Ответ №1:

Ответ не содержит заголовков, поэтому java отклоняет его

 wget "https://www.strava.cz/foxisapi/foxisapi.dll/istravne.istravne.process?xmljidelnickyAamp;zarizeni=3148" -O so-69226464.html
--2021-09-17 13:44:29--  https://www.strava.cz/foxisapi/foxisapi.dll/istravne.istravne.process?xmljidelnickyAamp;zarizeni=3148
Resolving www.strava.cz (www.strava.cz)... 82.99.180.77
Connecting to www.strava.cz (www.strava.cz)|82.99.180.77|:443... connected.
HTTP request sent, awaiting response... 200 No headers, assuming HTTP/0.9
Length: unspecified
 

Этот класс java, выполняющий необработанный HTTP-запрос GET, может получить содержимое. На основе этой страницы.
Отправленный запрос является

 GET /foxisapi/foxisapi.dll/istravne.istravne.process?xmljidelnickyAamp;zarizeni=3148 HTTP/1.1rn
User-Agent: RawHttpGetrn
Host: www.strava.czrn
Accept: */*rn
 

Java-код:

 import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

import javax.net.ssl.SSLSocketFactory;

public class RawHttpGet {
    private static String hostname = "www.strava.cz";
    public static void main(String[] args) throws IOException {
        Socket socket = SSLSocketFactory.getDefault().createSocket(hostname, 443);

        // UTF-8 encdoding
        //BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
        // Encoding for this request
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "Cp1250"));
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        
        StringBuffer buff = new StringBuffer("GET /foxisapi/foxisapi.dll/istravne.istravne.process?xmljidelnickyAamp;zarizeni=3148 HTTP/1.1rn");
        buff.append("User-Agent: RawHttpGetrn");
        buff.append("Accept: */*rn");
        buff.append("Host: "   hostname   "rn");
        buff.append("rn");
        System.out.println(" * Request");
        System.out.println(buff.toString());
        // send message
        out.write(buff.toString());
        out.flush();

        // read response
        System.out.println(" * Response");
        // Default system encoding
        //System.out.println(new String(socket.getInputStream().readAllBytes()));
        // Encoding for this request
        System.out.println(new String(socket.getInputStream().readAllBytes(), "Cp1250"));

        out.close();
        in.close();
    }
}
 

Комментарии:

1. Работает именно так, как я и ожидал. Спасибо за ваш ответ!

2. @Mayuna исправил код для использования SSL-порта 443. Вы все еще можете использовать порт 80, соответствующим образом комментируя/раскомментируя.

3. не преобразуйте xml в символы/строки/считыватели. это отличный способ уничтожить. сохраняйте его в виде байтов и потоков ввода/вывода

4. используйте InputStream и OutputStream и byte[] для копирования байтов между ними.

5. Спасибо, я обновлю свой код.