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