मैं WebView से वेब पेज की सामग्री कैसे प्राप्त करूं?


86

Android पर, मेरे पास WebViewएक पृष्ठ प्रदर्शित हो रहा है ।

फिर से पेज रिक्वेस्ट किए बिना मुझे पेज सोर्स कैसे मिलेगा?

ऐसा लगता है WebViewकि किसी प्रकार की getPageSource()विधि होनी चाहिए जो एक स्ट्रिंग लौटाती है, लेकिन अफसोस यह नहीं है।

यदि मैं जावास्क्रिप्ट सक्षम करता हूं, तो सामग्री प्राप्त करने के लिए इस कॉल में डालने के लिए उपयुक्त जावास्क्रिप्ट क्या है?

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

वेबव्यू window.interface.processHTML ($ (\ "body \") से HTML सामग्री प्राप्त करने के लिए jquery स्क्रिप्ट और js इंटरफ़ेस का उपयोग करें। html ());
DroidBot


आप 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()निष्पादित होने से पहले पृष्ठ की सामग्री जावास्क्रिप्ट के माध्यम से गतिशील रूप से बदल सकती है ।
पॉल लामर्ट्स्मा

3
यह बहुत अच्छा है, लेकिन विधि browser.loadUrlको कॉल करने onPageFinishedका कारण onPageFinishedफिर से बुलाया जाएगा। आप कॉल करने से पहले यह देखना चाहते हैं कि यह पहली कॉल है onPageFinishedया नहीं browser.loadUrl
यी एच।

धन्यवाद @Blundell यह मेरे लिए काम किया। मैं जानना चाहता हूं कि इसे एक सेवा के रूप में कैसे लागू किया जा सकता है । चूंकि परिणामों को संग्रहीत करने के लिए लेआउट और वेबव्यू के बिना एक सेवा है। क्या वेबव्यू से अलग किसी अन्य ऑब्जेक्ट में डेटा डालने का एक तरीका है ताकि हम परिणामी HTML कोड प्राप्त करने के लिए जावास्क्रिप्ट डाल सकें?
कुल

@ टोटलिस और भी आसान है String html = new Scanner(new DefaultHttpClient().execute(new HttpGet("www.the url")).getEntity().getContent(), "UTF-8").useDelimiter("\\A").next();(संक्षिप्त में टिप्पणी में फिट होने के लिए :-))
ब्लंडेल

1
RunOnUiThread (नया Runnable () {... सार्वजनिक शून्य प्रक्रिया HTML में सम्मिलित करना न भूलें।
CoolMind

34

प्रति अंक 12987 , ब्लंडल का जवाब क्रैश (कम से कम मेरे 2.3 वीएम पर)। इसके बजाय, मैं एक विशेष उपसर्ग के साथ कंसोल.लॉग को कॉल को इंटरसेप्ट करता हूं:

// 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 के आधार पर एक उत्तर है , लेकिन मुझे लगता है कि जावास्क्रिप्ट को इस प्रकार बदलना बेहतर और सरल है।

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
यह कुकीज़ नहीं ले जाएगा।
कीथ एडलर

1
यह दृष्टिकोण कॅप्चा संवाद
हेक्टर

4

मैं @ jluckyiv के उत्तर से कोड का उपयोग करके इसे प्राप्त करने में कामयाब रहा, लेकिन मुझे @JavaScriptInterface में प्रक्रिया HTML विधि में @JavascriptInterface एनोटेशन को जोड़ना पड़ा।

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

1

यदि आपके लक्ष्यवेक वर्जन> = 17 है - तो आपको @JavascriptInterface के साथ विधि को एनोटेट करने की भी आवश्यकता है क्योंकि SDK 17 में नई सुरक्षा आवश्यकताएं हैं, अर्थात सभी जावास्क्रिप्ट विधियों को JJavcriptcriptterterface के साथ एनोटेट किया जाना चाहिए। अन्यथा आपको त्रुटि दिखाई देगी जैसे: अनकहा टाइप टाइप: ऑब्जेक्ट [ऑब्जेक्ट ऑब्जेक्ट] में कोई प्रक्रिया नहीं है 'प्रक्रिया HTML' null] 1


0

यदि आप किटकैट और इसके बाद के संस्करण पर काम कर रहे हैं, तो आप अपने वेबव्यू में जा रहे सभी अनुरोधों और प्रतिक्रियाओं को खोजने के लिए क्रोम रिमोट डिबगिंग टूल का उपयोग कर सकते हैं और देखे गए पृष्ठ का HTML स्रोत कोड भी।

https://developer.chrome.com/devtools/docs/remote-debugging

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.