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のコードを見ていたのですが、AndroidのSDKHttpURLConnection
が使われているところで詰んでしまいました。
frameworkのところまで調べていくと、 RuntimeInit
というクラスで、デフォルトのUAに使われる値が生成されていました。
- RuntimeInit.java
/** * 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 SDKのHttpURLConnection
のデフォルトの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