メモ2ブログ

メモtoウェブログ。旧ブログはこちら。 http://sakebook.blogspot.jp/

jsoupのデフォルトのUser-Agentはなんなのか。

jsoup

JavaでHTMLをいい感じにParseできる便利なライブラリです。 WebページにアクセスしてHTMLを取得し、それを加工することでWebページ内のコンテンツを簡単に取得することができます。

スクレイピング先が、User-Agent(UA)によって表示を変えている場合、それに応じてjsoupのUAを変更しなければ、思っていたコンテンツが取得できない場合があります。

User-Agentの設定

Connection#userAgent(String) で設定できます。次のようにすることで設定されたUAを確認できます。

String url = "http://www.useragentstring.com/";
Connection con = Jsoup.connect(url);
con.userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0");
Doc doc = con.get();
doc.getElementById("uas_textfeld").val());

メソッドで指定した通り、

Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0

が設定されているのがわかります。

未設定時

未設定のときにどうなるのか調べてみました。 Androidエミュレータで前述のようにし、UAの設定をしないと次のようになりました。

  • Genymotion
Dalvik/2.1.0 (Linux; U; Android 5.0; Nexus 5 - 5.0.0 - API 21 - 1080x1920_1 Build/LRX21M)

どこで誰が設定しているんだろうと思い、jsoupのコードを見ていたのですが、AndroidSDKHttpURLConnectionが使われているところで詰んでしまいました。

frameworkのところまで調べていくと、 RuntimeInitというクラスで、デフォルトのUAに使われる値が生成されていました。

    /**
     * Returns an HTTP user agent of the form
     * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)".
     */
    private static String getDefaultUserAgent() {
        StringBuilder result = new StringBuilder(64);
        result.append("Dalvik/");
        result.append(System.getProperty("java.vm.version")); // such as 1.1.0
        result.append(" (Linux; U; Android ");
    
        String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
        result.append(version.length() > 0 ? version : "1.0");
    
        // add the model for the release build
        if ("REL".equals(Build.VERSION.CODENAME)) {
            String model = Build.MODEL;
            if (model.length() > 0) {
                result.append("; ");
                result.append(model);
            }
        }
        String id = Build.ID; // "MASTER" or "M4-rc20"
        if (id.length() > 0) {
            result.append(" Build/");
            result.append(id);
        }
        result.append(")");
        return result.toString();
    }

他のやり方ではどのように表示されるのか、いろんな方法でUAが確認できるサイトにアクセスしてみました。

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
Mozilla/5.0 (Linux; Android 6.0.1; Nexus 6 Build/MMB29V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.105 Mobile Safari/537.36
curl/7.43.0
  • httpie
HTTPie/0.8.0

httpieが一番わかりやすく、ソースを見ると、

...
DEFAULT_UA = 'HTTPie/%s' % __version__
...
def get_default_headers(args):
    default_headers = {
        'User-Agent': DEFAULT_UA
    }
    ...

となっていたので、アクセスするプログラムが決めているのだとわかりました。 curlやブラウザなどは中がわからなかったのですが、おそらく内部で同じように自分のUAを設定しているのだと思います。

間接的で、直接はわかっていないのですが、少しスッキリしました。

jsoupのデフォルトのUA

Androidから使うときは、Android SDKHttpURLConnectionのデフォルトのUAが適応され、Android端末のUAとなります。

参考

jsoup: Java HTML Parser / jsoup

JSoup UserAgent, how to set it right? / StackOverFlow

User Agent String.Com / UserAgentString.com

What's the default Jsoup User Agent string? / StackOverFlow

Cross Reference: RuntimeInit.java / OpenGrok

jkbrzt/httpie / GitHub