Robloxの外貨両替から統計データを収集して分析しようとしています。したがって、キャッシュされた結果ではなく、最新のデータが必要です。しかし、私が何をしても、結果はまだキャッシュされているようです。最も直感的なオプションであるsetUseCaches()
は効果がなかったようで、ヘッダーを手動でCache-Control: no-cache
として設定することも機能しないようです。 Fiddler2を使用してCacheヘッダーを調べたところ、その値がCache-Control: max-age=0
であることがわかりましたが、プログラムの動作も変更されていないようです。関連するコードは次のとおりです。
URL:
private final static String URL = "http://www.roblox.com/my/money.aspx#/#TradeCurrency_tab";
GETリクエスト:
URLConnection socket = new URL( URL ).openConnection( );
socket.setUseCaches( false );
socket.setDefaultUseCaches( false );
HttpURLConnection conn = ( HttpURLConnection )socket;
conn.setUseCaches( false );
conn.setDefaultUseCaches( false );
conn.setRequestProperty( "Pragma", "no-cache" );
conn.setRequestProperty( "Expires", "0" );
conn.setRequestProperty( "Cookie", ".ROBLOSECURITY=" + ROBLOSECURITY );
conn.setRequestProperty( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" );
conn.setRequestProperty( "Accept-Language", "en-US,en;q=0.8" );
conn.setRequestProperty( "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36" );
conn.setDoInput( true );
conn.setRequestMethod( "GET" );
conn.connect();
Scanner data = new Scanner( conn.getInputStream() );
data.useDelimiter( "\\A" );
String result = data.next();
data.close( );
conn.disconnect();
プログラムを再起動するたびに一意の結果が返されるが、プログラムの実行時には返されないことに注意することが重要な場合とそうでない場合があります。
更新:
Wiresharkの分析(前回からコードを少し調整しました):
GET /my/money.aspx HTTP/1.1
Pragma: no-cache
Expires: 0
Cookie: .ROBLOSECURITY=_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|*sensitive*
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Cache-Control: no-cache
Host: www.roblox.com
Connection: keep-alive
HTTP/1.1 200 OK
Cache-Control: private, s-maxage=0
Content-Type: text/html; charset=utf-8
Set-Cookie: rbx-ip=; domain=roblox.com; path=/; HttpOnly
Set-Cookie: RBXSource=rbx_acquisition_time=1/4/2016 12:45:21 AM&rbx_acquisition_referrer=&rbx_medium=Direct&rbx_source=&rbx_campaign=&rbx_adgroup=&rbx_keyword=&rbx_matchtype=&rbx_send_info=0; domain=roblox.com; expires=Wed, 03-Feb-2016 06:45:21 GMT; path=/
Access-Control-Allow-Credentials: true
Set-Cookie: rbx-ip=; domain=roblox.com; path=/; HttpOnly
Set-Cookie: RBXSource=rbx_acquisition_time=1/4/2016 12:45:21 AM&rbx_acquisition_referrer=&rbx_medium=Direct&rbx_source=&rbx_campaign=&rbx_adgroup=&rbx_keyword=&rbx_matchtype=&rbx_send_info=1; domain=roblox.com; expires=Wed, 03-Feb-2016 06:45:21 GMT; path=/
Set-Cookie: RBXEventTrackerV2=CreateDate=1/4/2016 12:45:21 AM&rbxid=59210735&browserid=3940274345; domain=roblox.com; expires=Fri, 22-May-2043 05:45:21 GMT; path=/
Set-Cookie: GuestData=UserID=-856460986; domain=.roblox.com; expires=Fri, 22-May-2043 05:45:21 GMT; path=/
P3P: CP="CAO DSP COR CURa ADMa DEVa OUR IND PHY ONL UNI COM NAV INT DEM PRE"
Date: Mon, 04 Jan 2016 06:45:20 GMT
Content-Length: 153751
キャッシュがサーバー側で発生する場合は、URLにキャッシュバスターを追加します。
HttpURLConnection conn = ( HttpURLConnection )new URL( URL + "?_=" + System.currentTimeMillis() ).openConnection( );
ローカルのHttpURLConnection
に独自のキャッシュをバイパスするように指示していないことに気付きました。
HttpURLConnection
はメソッドsetUseCaches(boolean)
をURLConnection
から継承します。 Javadoc for setUseCaches(boolean)
から
このURLConnectionのuseCachesフィールドの値を指定された値に設定します。
一部のプロトコルはドキュメントのキャッシュを行います。場合によっては、キャッシュを「トンネリング」して無視できることが重要です(たとえば、ブラウザの「再読み込み」ボタン)。接続のUseCachesフラグがtrueの場合、接続は可能な限りのキャッシュを使用できます。 falseの場合、キャッシュは無視されます。デフォルト値はDefaultUseCachesから取得され、デフォルトはtrueです。
次のヘッダーを試しましたか?
Cache-Control: no-cache
Pragma: no-cache
If-Modified-Since: Sat, 1 Jan 2000 00:00:00 GMT
ほとんどのキャッシュ設定を試したように見えます。それはあなたのクライアントではなく、これを引き起こす彼らのサービスである可能性があります。あなたのwireshark情報から、「ConnectionKeep-Alive」があることがわかります。プログラムを再起動するたびにキャッシュされていない結果が得られると言うので、おそらくそれを「接続を閉じる」に設定してみてください。
これは本番環境では理想的ではないかもしれませんが、何が起こっているのかについての洞察を得ることができるかもしれません。
問題を正確に特定するためのコンテキスト(特定のコードが複数回呼び出される方法)がありませんが、リクエストごとに新しいオブジェクトをインスタンス化する代わりに、socket
オブジェクトを再利用したことが原因である可能性があります。
接続が開かれると、useCache
の設定は重要ではなくなります。 Sun.net.www.protocol.http.HttpURLConnection#connect
の実装を見てください。
protected void plainConnect() throws IOException {
if (connected) {
return;
}
// try to see if request can be served from local cache
if (cacheHandler != null && getUseCaches()) {
// ..
}
接続が開かれた場合、接続はすぐに戻り、既存のInputStream
インスタンスを再利用します。
URLConnection
ソケットを開く前に、URLに対して次の操作を行うことをお勧めします。
URLConnection socket = new URL( URL.replaceFirst("#", "?cacheFrom=" + System.currentTimeMillis()+"#") ).openConnection( );