Hatena::Groupandroid

keigoiの日記

 | 

2010-02-11

WebViewを使ったスクレイピング / scraping a page using the WebView in a Service

21:56

AndroidのwebブラウザコンポーネントWebViewはHTMLのparsingをやっているはずなので、スクレイピングに使えないか?と考えた。

  • 新しいライブラリに依存するよりも設計がシンプルになり学習コストも低い
  • Google自慢のJavaScriptエンジンを使うので、効率がよいかもしれない。いいかげんなHTMLパーザやxpathエンジンはリソースがふんだんにあるPCやサーバ上での動作を前提にしており、Android向きではないかも。

実現するにあたって次の問題があるのではないかと思う:

  • WebViewは「重い」。 スクレイピングに不要なレンダリング処理等で時間がかかるかも。 (上と矛盾する)
  • WebViewはビューなので Service では動かない(バックグラウンドで実行できない)かも

何かしらご存知の方はコメントを頂きたいですm(__)m

さしあたり Serviceから WebView を呼ぶコードを書いてみた。

パフォーマンス

www.google.co.jp を読みに行って、ページのタイトルをJavaScriptで取得してtoastで表示するコードを書いた。

ページのロード開始から完了までで、エミュレータ上で3秒くらい, 実機(3G)で6.5秒(ただし2回目以降は4秒, 1.5秒.. と速くなる傾向, 分散も大きい)。

バックグラウンド処理なら許容範囲内かもしれない。

今後の課題

  • 内部的なレンダリングやJavaScriptの実行のせいで遅いのかもしれない。 traceviewでパフォーマンスを分析したい
  • そもそもServiceでWebViewを動かす是非について androidMLあたりに聞いたみたい

コード

import android.app.Service;
import android.content.Intent;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MyService extends Service {
	
	String title; // JavaScriptからのコールバックで設定される
	long start; // onStartが呼ばれた時刻
	long fetch; // loadUrlを呼んだ時刻
	WebView myWebView; 
	
	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	@Override
	public void onDestroy() {
		long cur = System.currentTimeMillis();
		long elapsed1 = cur - start, elapsed2 = cur - fetch;
		
		String msg = "finishing the service.."+((double)elapsed1/1000)+" sec elapsed from beginning. fetch: "+
			((double)elapsed2/1000)+" sec. page title:"+title;
		Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
		Log.i("MyService", msg);
	}
	

	@Override
	public void onStart(Intent intent, int startId) {
		Log.i("MyService", "starting the service");
		Toast.makeText(this, "starting the service", Toast.LENGTH_SHORT).show();
		start = System.currentTimeMillis();
		
		// このスレッドのハンドラにWebViewの処理をポスト (他スレッドではうまくいかない)
		new Handler().post(new Runnable() {public void run() {
	        myWebView = new WebView(MyService.this);
	        
	        // キャッシュを無効に (重要, デフォルトのままだとキャッシュのせいで?ダウンロードが発生しない)
	        myWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
	        
	        // 画像のロードを無効に / JavaScriptを無効に / ウィンドウを不可視に
	        myWebView.getSettings().setLoadsImagesAutomatically(false);
	        myWebView.getSettings().setJavaScriptEnabled(false);	        
	        myWebView.setVisibility(View.INVISIBLE);

	        // demoという変数で DemoJavaScriptInterfaceへのアクセスを可能にする
	        myWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");

	        // ページロードの終了時に実行するアクションをWebViewClientとともに登録
	        myWebView.setWebViewClient(new WebViewClient(){
					@Override
					public void onPageFinished(WebView view, String url) {
				        // Debug.stopMethodTracing();
						// ページのロードを終了
						Toast.makeText(MyService.this, "pageload finished", Toast.LENGTH_LONG).show();
						Log.i("MyService", "pageload finished");

						// JavaScriptを実行する
				        myWebView.getSettings().setJavaScriptEnabled(true);	        
						myWebView.loadUrl("javascript:demo.hello(document.title);");
						Log.i("MyService", "javascript execution issued.");
					}
	        	});
	        
	        // ページをロード
	        fetch = System.currentTimeMillis();
	        // Debug.startMethodTracing("fetch");
			myWebView.loadUrl("http://www.google.co.jp/");
		}});
	}

	// JavaScript側からコールバックされるオブジェクト
    final class DemoJavaScriptInterface {
        DemoJavaScriptInterface() {
        }
        public void hello(String title) {
			Log.i("MyService", "hello!");
			Toast.makeText(MyService.this, "hello!, received text:"+title, Toast.LENGTH_SHORT).show();
        	MyService.this.title = title;
        	stopSelf(); // サービスを止める
        }
    }
}

Androidのコーディングに慣れていないせいもあって思いのほか時間がかかった。

loadUrlが成功しているにもかかわらずページがロードされず(HTTP接続がない)、原因の特定に苦労した。

traceview でトレースしつつandroidのソースとにらめっこしながら分析したらば分かったのだが、どうやらキャッシュの設定のせいでネットワーク接続をしなかったようだった。

まいむぞうまいむぞう 2010/02/12 11:59 フォローしました。
http://fromnorth.blogspot.com/2010/02/webview.html
うお。トラックバック失敗したかも?

keigoikeigoi 2010/02/12 18:13 ありがとうございます! ML で返信しました。
http://groups.google.co.jp/group/android-group-japan/t/b8b4d6aed362004b

ConyersConyers 2011/10/01 13:08 Good point. I hadn't thuohgt about it quite that way. :)

znwowhjhznwowhjh 2011/10/02 22:18 UxxaBd , [url=http://zmafdlqkkgiz.com/]zmafdlqkkgiz[/url], [link=http://vonkwskugbtx.com/]vonkwskugbtx[/link], http://ebjboqdxcblt.com/

kwtlliuqvuukwtlliuqvuu 2011/10/03 20:49 BbM0Wg <a href="http://iqkozgbtiblf.com/">iqkozgbtiblf</a>

pfklgbepfklgbe 2011/10/07 00:11 Cc9xJC , [url=http://knfahhhzqmil.com/]knfahhhzqmil[/url], [link=http://xsxixfpnjbtm.com/]xsxixfpnjbtm[/link], http://lesgqgeqgrwv.com/

tatatatatata 2012/07/07 14:20 こんにちは
サービスからwebviewを呼ぶと見た目どうなるんでしょうか?
activityのようにビューが表示されるんですか?

EmirEmir 2012/10/28 13:04 Please teach the rest of these itrnenet hooligans how to write and research!

afhxvjlskrafhxvjlskr 2012/10/29 15:29 pi8icf <a href="http://outvflqeyedr.com/">outvflqeyedr</a>

afhxvjlskrafhxvjlskr 2012/10/29 15:30 pi8icf <a href="http://outvflqeyedr.com/">outvflqeyedr</a>

dobicasqwhdobicasqwh 2013/07/26 20:24 bxpbzboespje, <a href="http://www.mwjgeafvbs.com/">sgiobeclhz</a> , [url=http://www.nnafmahmtf.com/]mfocctbhjm[/url], http://www.zsnvikzmee.com/ sgiobeclhz

cymrruhimrcymrruhimr 2013/07/30 05:30 aytjrboespje, <a href="http://www.dvbnzragro.com/">veeoqhcprv</a> , [url=http://www.nndnqatmcq.com/]eyuhqucanf[/url], http://www.adiozrwuef.com/ veeoqhcprv

sfvcjszvwzsfvcjszvwz 2013/08/27 20:40 qtvviboespje, <a href="http://www.sigpotmlyd.com/">mmnvccqdwb</a> , [url=http://www.ohrejyxmzv.com/]vsxxivupui[/url], http://www.hrwwhfrcdl.com/ mmnvccqdwb

rwpvbxchlxrwpvbxchlx 2013/11/23 06:37 dcbyiboespje, <a href="http://www.aljvgkglsg.com/">utmweoxgll</a> , [url=http://www.nvzdnkncrp.com/]gxlhozcqbn[/url], http://www.zrwmqjxhaa.com/ utmweoxgll

qawvjdyoooqawvjdyooo 2014/06/24 15:02 aatnsboespje, <a href="http://www.iyzgonfqne.com/">zahftvpndw</a> , [url=http://www.uwbeamfvgt.com/]eoonrvaxqn[/url], http://www.sukzgcujgh.com/ zahftvpndw

IbliIbli 2015/10/09 18:26 A plneisagly rational answer. Good to hear from you.

ImamImam 2015/10/13 08:48 I told my kids we'd play after I found what I <a href="http://okhgotbrhp.com">needde.</a> Damnit.

ShiellaShiella 2015/10/13 15:52 This has made my day. I wish all potginss were this good. http://uohibhu.com [url=http://ncheaxtvd.com]ncheaxtvd[/url] [link=http://eqlwkkegt.com]eqlwkkegt[/link]

ゲスト



 |