Ошибка разрешения URL-адреса википедии с использованием символа Юникода с URL-адресом Java - PullRequest
4 голосов
/ 04 июня 2011

У меня проблемы с получением URL-адресов Википедии, включая Юникод!

С учетом названия страницы, например: 1992 \ u201393_UE_Lleida_seasonnow

Просто простой URL-адрес ... http://en.wikipedia.org/wiki/1992\u201393_UE_Lleida_seasonnow

Использование URLEncoder (установлен на UTF-8) .... http://en.wikipedia.org/wiki/1992%5Cu201393_UE_Lleida_seasonnow

Когда я пытаюсь разрешить любой URL, я ничего не получаю.Если я скопирую URL в свой браузер, я тоже ничего не получу - только если я на самом деле скопирую символ юникода, чтобы получить страницу.

Есть ли в википедии какой-то странный способ кодировать юникод в URL?Или я просто делаю что-то глупое?

Вот код, который я использую:

URL url = new URL("http://en.wikipedia.org/wiki/"+x);
System.out.println("trying "+url);  

// Attempt to open the wiki page
InputStream is;
        try{ is = url.openStream();
} catch(Exception e){ return null; }

Ответы [ 4 ]

2 голосов
/ 04 июня 2011

Есть ли в Википедии какой-то странный способ кодировать юникод в URL?

Это не совсем странно, это стандартное использование IRI с. ИРИ:

http://en.wikipedia.org/wiki/2009–10_UE_Lleida_season

, который включает Unicode en-dash, эквивалентен URI:

http://en.wikipedia.org/wiki/2009%E2%80%9310_UE_Lleida_season

Вы можете включить в ссылки форму IRI, и она будет работать в современных браузерах. Но многим сетевым библиотекам, включая Java и более старые браузеры, требуются URI только для ASCII. (Современные браузеры по-прежнему будут показывать симпатичную версию IRI в адресной строке, даже если вы связались с ней с помощью закодированной версии URI.)

Чтобы преобразовать IRI в URI в целом, вы используете алгоритм IDN для имени хоста и кодируете URL-адреса любых других не ASCII-символов в виде байтов UTF-8. В вашем случае это должно быть:

String urlencoded= URLEncoder.encode(x, "utf-8").replace("+", "%20");
URL url= new URL("http://en.wikipedia.org/wiki/"+urlencoded);

Примечание: замена + на %20 необходима для получения значений x с пробелами в работе. URLEncoder делает application/x-www-form-urlencoded -кодирование как использование в строках запроса. Но в таком сегменте пути-URL правило + -means-space не применяется. Пробелы в путях должны быть закодированы с помощью обычного URL-кодирования до %20.

Опять же ... в конкретном случае Википедии, для удобства чтения, они заменяют пробелы подчеркиванием вместо этого, так что вам, вероятно, лучше заменить "+" на "_" напрямую. Версия %20 все еще будет работать, потому что они перенаправляют оттуда к версии с подчеркиванием.

2 голосов
/ 04 июня 2011

Правильный URI: http://en.wikipedia.org/wiki/2009%E2%80%9310_UE_Lleida_season.

Многие браузеры отображают литералы вместо кодированных в процентах escape-последовательностей.Это считается более удобным для пользователя.Однако правильно закодированные URI должны использовать процентное кодирование для символов, не разрешенных в path part :

   path          = path-abempty    ; begins with "/" or is empty
                 / path-absolute   ; begins with "/" but not "//"
                 / path-noscheme   ; begins with a non-colon segment
                 / path-rootless   ; begins with a segment
                 / path-empty      ; zero characters
   path-abempty  = *( "/" segment )
   path-absolute = "/" [ segment-nz *( "/" segment ) ]
   path-noscheme = segment-nz-nc *( "/" segment )
   path-rootless = segment-nz *( "/" segment )
   path-empty    = 0<pchar>
   segment       = *pchar
   segment-nz    = 1*pchar
   segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
                 ; non-zero-length segment without any colon ":"
   pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
   pct-encoded   = "%" HEXDIG HEXDIG
   unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
   sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
                 / "*" / "+" / "," / ";" / "="

Класс URI может помочьВы с такими последовательностями:

  • Символы в категории other разрешены везде, где RFC 2396 разрешает экранированные октеты, то есть в пользовательской информации путь, запрос,и фрагменты компонентов, а также в компоненте полномочий, если полномочия основаны на реестре.Это позволяет URI содержать символы Unicode, которые не входят в набор символов US-ASCII.
String literal = "http://en.wikipedia.org/wiki/1992\u201393_UE_Lleida_seasonnow";
URI uri = new URI(literal);
System.out.println(uri.toASCIIString());

Подробнее о кодировке URI можно прочитать здесь .

1 голос
/ 21 августа 2013

Вот более простой способ кодирования URL в ответе Чи:

static String encodeUrl(String urlToEncode) throws URISyntaxException {
    return new URI(urlToEncode).toASCIIString();
}

См. этот ответ для пояснения.

1 голос
/ 03 июня 2013

Вот простой алгоритм для кодирования URL-адресов, которые используют Unicode, так что вы можете использовать HttpURLConnection для их получения:

import static org.junit.Assert.*;

import java.net.URLEncoder;

import org.apache.commons.lang.CharUtils;
import org.junit.Test;

public class InternationalURLEncoderTest {

    static String encodeUrl(String urlToEncode) {
        String[] pathSegments = urlToEncode.split("((?<=/)|(?=/))");
        StringBuilder encodedUrlBuilder = new StringBuilder();
        for (String pathSegment : pathSegments) {
            boolean needsEncoding = false;
            for (char ch : pathSegment.toCharArray()) {
                if (!CharUtils.isAscii(ch)) {
                    needsEncoding = true;
                    break;
                }
            }
            String encodedSegment = needsEncoding ? URLEncoder
                    .encode(pathSegment) : pathSegment;
            encodedUrlBuilder.append(encodedSegment);
        }
        return encodedUrlBuilder.toString();
    }

    @Test
    public void test() {
        assertEquals(
                "http://www.chinatimes.com/realtimenews/%E5%8D%97%E6%8A%95%E4%B8%80%E8%90%AC%E5%A4%9A%E6%88%B6%E5%A4%A7%E5%81%9C%E9%9B%BB-%E4%B9%9D%E6%88%90%E4%BB%A5%E4%B8%8A%E6%81%A2%E5%BE%A9%E4%BE%9B%E9%9B%BB-20130603003259-260401",
                encodeUrl("http://www.chinatimes.com/realtimenews/南投一萬多戶大停電-九成以上恢復供電-20130603003259-260401"));
        assertEquals("http://www.ttv.com.tw/",
                encodeUrl("http://www.ttv.com.tw/"));
        assertEquals("http://www.ttv.com.tw",
                encodeUrl("http://www.ttv.com.tw"));
        assertEquals("http://www.rt-drive.com.tw/shopping/?st=16",
                encodeUrl("http://www.rt-drive.com.tw/shopping/?st=16"));
    }

}

Алгоритм был написан с использованием этих ответов на разбиение строк и обнаружение символов Unicode

...