WebView에서 웹 페이지 콘텐츠를 가져 오려면 어떻게합니까?


86

Android에서는 WebView페이지를 표시하는 것이 있습니다.

페이지를 다시 요청하지 않고 페이지 소스를 얻으려면 어떻게합니까?

보인다 WebView어떤 종류가 있어야 getPageSource()문자열을 반환하는 방법을하지만, 슬프게도 그렇지 않습니다.

JavaScript를 활성화하는 경우 내용을 가져 오기 위해이 호출에 넣을 적절한 JavaScript는 무엇입니까?

webview.loadUrl("javascript:(function() { " +  
    "document.getElementsByTagName('body')[0].style.color = 'red'; " +  
    "})()");  

jquery 스크립트와 js 인터페이스를 사용하여 webview window.interface.processHTML ($ (\ "body \"). html ());
DroidBot 2013-06-21


HTTP 요청을 사용하여 HTML로 응답을 얻을 수 있지만 일부 페이지에서 게시 데이터를로드해야하는 경우 (예 : 사용자 자격 증명 등)이 접근 방식은 실패합니다. 그렇게 할 수 있다면 어떤 웹 사이트에서든 자신 만의 안드로이드 앱을 만들 수 있기 때문에 그렇게되어야한다고 생각합니다.

답변:


161

나는 이것이 늦은 대답이라는 것을 알고 있지만 같은 문제가 있었기 때문에이 질문을 찾았습니다. lexandera.com 의이 게시물 에서 답을 찾은 것 같습니다. 아래 코드는 기본적으로 사이트에서 잘라내어 붙여 넣은 것입니다. 트릭을하는 것 같습니다.

final Context myApp = this;

/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface
{
    @JavascriptInterface
    @SuppressWarnings("unused")
    public void processHTML(String html)
    {
        // process the html as needed by the app
    }
}

final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */
browser.getSettings().setJavaScriptEnabled(true);

/* Register a new JavaScript interface called HTMLOUT */
browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");

/* WebViewClient must be set BEFORE calling loadUrl! */
browser.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url)
    {
        /* This call inject JavaScript into the page which just finished loading. */
        browser.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
    }
});

/* load a web page */
browser.loadUrl("http://lexandera.com/files/jsexamples/gethtml.html");

6
이것은 페이지의 원시 HTML이 아닐 수도 있습니다. 페이지 콘텐츠 onPageFinished()가 실행 되기 전에 JavaScript를 통해 동적으로 변경되었을 수 있습니다 .
Paul Lammertsma

3
그것은 좋은,하지만 방법 호출 browser.loadUrl에하는 onPageFinished원인이됩니다 onPageFinished다시 호출 할 수 있습니다. 전화 onPageFinished하기 전에 의 첫 번째 전화인지 아닌지 확인하는 것이 browser.loadUrl좋습니다.
이순신 H.

감사합니다 @ Blundell 그것은 나에게 일했습니다. 이것이 어떻게 서비스구현 될 수 있는지 알고 싶습니다 . 결과를 저장하는 레이아웃과 웹뷰가없는 서비스이기 때문입니다. 결과 html 코드를 얻기 위해 javascript를 넣을 수 있도록 webView와 다른 다른 객체에 데이터를 넣는 방법이 있습니까?
Totalys

심지어 쉽게 @Totalys String html = new Scanner(new DefaultHttpClient().execute(new HttpGet("www.the url")).getEntity().getContent(), "UTF-8").useDelimiter("\\A").next();(약어는 :-) 코멘트에 맞게)
Blundell은

1
runOnUiThread (new Runnable () {...를 public void processHTML에 삽입하는 것을 잊지 마십시오.
CoolMind

34

문제 12987 , Blundell은의 대답은 (내 2.3 VM에 적어도) 충돌합니다. 대신 특수 접두사가있는 console.log 호출을 가로 챕니다.

// intercept calls to console.log
web.setWebChromeClient(new WebChromeClient() {
    public boolean onConsoleMessage(ConsoleMessage cmsg)
    {
        // check secret prefix
        if (cmsg.message().startsWith("MAGIC"))
        {
            String msg = cmsg.message().substring(5); // strip off prefix

            /* process HTML */

            return true;
        }

        return false;
    }
});

// inject the JavaScript on page load
web.setWebViewClient(new WebViewClient() {
    public void onPageFinished(WebView view, String address)
    {
        // have the page spill its guts, with a secret prefix
        view.loadUrl("javascript:console.log('MAGIC'+document.getElementsByTagName('html')[0].innerHTML);");
    }
});

web.loadUrl("http://www.google.com");

17

이것은 jluckyiv를 기반으로 한 답변 이지만 다음과 같이 Javascript를 변경하는 것이 더 좋고 간단하다고 생각합니다.

browser.loadUrl("javascript:HTMLOUT.processHTML(document.documentElement.outerHTML);");

6

HTML을 별도로 가져온 다음 웹뷰에로드하는 것을 고려해 보셨습니까?

String fetchContent(WebView view, String url) throws IOException {
    HttpClient httpClient = new DefaultHttpClient();
    HttpGet get = new HttpGet(url);
    HttpResponse response = httpClient.execute(get);
    StatusLine statusLine = response.getStatusLine();
    int statusCode = statusLine.getStatusCode();
    HttpEntity entity = response.getEntity();
    String html = EntityUtils.toString(entity); // assume html for simplicity
    view.loadDataWithBaseURL(url, html, "text/html", "utf-8", url); // todo: get mime, charset from entity
    if (statusCode != 200) {
        // handle fail
    }
    return html;
}

2
이것은 쿠키를 운반하지 않습니다.
Keith Adler

1
이 방법 트리거는 대화 보안 문자
헥터

4

@jluckyiv의 답변 코드를 사용하여이 작업을 수행했지만 MyJavaScriptInterface의 processHTML 메서드에 @JavascriptInterface 주석을 추가해야했습니다.

class MyJavaScriptInterface
{
    @SuppressWarnings("unused")
    @JavascriptInterface
    public void processHTML(String html)
    {
        // process the html as needed by the app
    }
}

1

targetSdkVersion이 17보다 크면 @JavascriptInterface로 메서드에 주석을 추가해야합니다. SDK 17에 새로운 보안 요구 사항이 있기 때문입니다. 즉, 모든 자바 스크립트 메서드는 @JavascriptInterface로 주석을 달아야합니다. 그렇지 않으면 다음과 같은 오류가 표시됩니다. Uncaught TypeError : Object [object Object] has no method 'processHTML'at null : 1


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.