4

「長年の読者、初めてのポスター」はこちら。

私が管理しているスペイン語の Wikiのボットを作成中です。Java を練習することが目的の 1 つであるため、ゼロから作成したかったのです。しかし、á、é、í、ó、ú などの非 ASCII 文字を含む URI に対して HttpClient を使用して GET リクエストを作成しようとすると、いくつかの問題が発生しました。

String url = "http://es.metroid.wikia.com/api.php?action=query&list=categorymembers&cmtitle=Categoría:Mejoras de las Botas"
method = new GetMethod(url);
client.executeMethod(method);

上記を実行すると、GetMethod は URI について不平を言います。

Exception in thread "main" java.lang.IllegalArgumentException: Invalid uri 'http://es.pruebaloca.wikia.com/api.php?action=query&list=categorymembers&cmtitle=Categoría:Mejoras%20de%20las%20Botas&cmlimit=500&format=xml': Invalid query
    at org.apache.commons.httpclient.HttpMethodBase.<init>(HttpMethodBase.java:222)
    at org.apache.commons.httpclient.methods.GetMethod.<init>(GetMethod.java:89)
    at net.metroidover.categorybot.http.HttpRequest.request(HttpRequest.java:69)
    at net.metroidover.categorybot.http.HttpRequest.request(HttpRequest.java:120)
    at net.metroidover.categorybot.http.Action.getCategoryMembers(Action.java:38)
    at net.metroidover.categorybot.bot.BotComponent.<init>(BotComponent.java:58)
    at net.metroidover.categorybot.bot.BotComponent.main(BotComponent.java:80)

スタック トレースに表示される URI では、スペースがエンコードされ%20ís がそのまま残されることに注意してください。まったく同じ URI がブラウザーで完全に機能しますが、GetMethod でそれを受け入れることができません。

私も次のことを試しました:

URI uri = new URI(url, false);
method = new GetMethod(uri.getEscapedURI());
client.executeMethod(method);

このようにURI、s はエスケープされましiたが、スペース ( %2520) は二重にエスケープされました...

http://es.metroid.wikia.com/api.php?action=query&list=categorymembers&cmtitle=Categor%C3%ADa:Mejoras%2520de%2520las%2520Botas&cmlimit=500&format=xml

ここで、クエリでスペースを使用しない場合、二重のエスケープはなく、目的の出力が得られます。したがって、ASCII 以外の文字の可能性がまったくない場合、URIクラスを使用する必要はなく、二重エスケープも発生しません。スペースの最初のエスケープを回避するために、次のことを試しました。

URI uri = new URI(url, true);
method = new GetMethod(uri.getEscapedURI());
client.executeMethod(method);

しかし、URIクラスはそれが好きではありませんでした:

org.apache.commons.httpclient.URIException: Invalid query
    at org.apache.commons.httpclient.URI.parseUriReference(URI.java:2049)
    at org.apache.commons.httpclient.URI.<init>(URI.java:167)
    at net.metroidover.categorybot.http.HttpRequest.request(HttpRequest.java:66)
    at net.metroidover.categorybot.http.HttpRequest.request(HttpRequest.java:121)
    at net.metroidover.categorybot.http.Action.getCategoryMembers(Action.java:38)
    at net.metroidover.categorybot.bot.BotComponent.<init>(BotComponent.java:58)
    at net.metroidover.categorybot.bot.BotComponent.main(BotComponent.java:80)
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
    at java.util.ArrayList.RangeCheck(ArrayList.java:547)
    at java.util.ArrayList.get(ArrayList.java:322)
    at net.metroidover.categorybot.http.Action.getCategoryMembers(Action.java:39)
    at net.metroidover.categorybot.bot.BotComponent.<init>(BotComponent.java:58)
    at net.metroidover.categorybot.bot.BotComponent.main(BotComponent.java:80)

この二重エスケープを回避する方法についての意見は大歓迎です。私はまったく運がなくてあちこちに潜んでいました。

ありがとう!

編集:私にとって最も効果的な解決策はparsifalのものですが、さらに、保存する必要のあるCookieを拒否しmethod.setPath(url)てパスを設定すると言いたいです:HttpMethod

Aug 26, 2011 4:07:08 PM org.apache.commons.httpclient.HttpMethodBase processCookieHeaders
WARNING: Cookie rejected: "wikicities_session=900beded4191ff880e09944c7c0aaf5a". Illegal path attribute "/". Path of origin: "http://es.metroid.wikia.com/api.php"

ただし、コンストラクターに URI を送信して を忘れるとsetPath(url)、Cookie は問題なく保存されます。

String url = "http://es.metroid.wikia.com/api.php";
NameValuePair[] query = { new NameValuePair("action", "query"), new NameValuePair("list", "categorymembers"),
            new NameValuePair("cmtitle", "Categoría:Mejoras de las Botas"), new NameValuePair("cmlimit", "500"),
            new NameValuePair("format", "xml") };
HttpMethod method = null;

...

method = new GetMethod(url);  // Or PostMethod(url)
method.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); // It had been like this the whole time
method.setQueryString(query);
client.executeMethod(method);
4

3 に答える 3

5

UrlEncoderqueryString 値 (queryString 全体ではなく) をエンコードするために使用することをお勧めします。

UrlEncoder.encode("Categoría:Mejoras de las Botas", "UTF-8");
于 2011-08-25T17:50:12.383 に答える
2

HttpMethodBaseのドキュメントを見ると、すべてのStringパラメーターを事前にエンコードする必要があるようです。最も簡単な解決策は、URL を段階的に構築することです。setPath()そのバリアントはsetQueryString()、名前と値のパラメーターの配列を取ります。

于 2011-08-25T17:49:23.800 に答える
-1

パラメータを as として追加してみませんか。NameValuePairここでの問題は、URL をエスケープすると、http:// などを含む URL 内のすべてがエスケープされることです。これが、システムが不平を言っている理由です。

を使用して引数だけをエスケープすることもできますURLEncoder.encode()。get パラメータをこれに渡し、戻り値を URL に追加するだけです。

String url = "http://es.metroid.wikia.com/api.php?"+URLEncoder.encode("action=query&list=categorymembers&cmtitle=Categoría:Mejoras de las Botas");

于 2011-08-25T17:50:27.727 に答える