Как получить HTML-контент из веб-просмотра? - PullRequest
106 голосов
/ 20 ноября 2011

Какой самый простой способ получить HTML-код из веб-просмотра?Я пробовал несколько методов из stackoverflow и Google, но не могу найти точный метод.Пожалуйста, укажите точный способ.

public class htmldecoder extends Activity implements OnClickListener,TextWatcher
{
TextView txturl;
Button btgo;
WebView wvbrowser;
TextView txtcode;
ImageButton btcode;
LinearLayout llayout;
int flagbtcode;
public void onCreate(Bundle savedInstanceState)
{
            super.onCreate(savedInstanceState);
                setContentView(R.layout.htmldecoder);

    txturl=(TextView)findViewById(R.id.txturl);

    btgo=(Button)findViewById(R.id.btgo);
    btgo.setOnClickListener(this);

    wvbrowser=(WebView)findViewById(R.id.wvbrowser);
    wvbrowser.setWebViewClient(new HelloWebViewClient());
    wvbrowser.getSettings().setJavaScriptEnabled(true);
    wvbrowser.getSettings().setPluginsEnabled(true);
    wvbrowser.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
    wvbrowser.addJavascriptInterface(new MyJavaScriptInterface(),"HTMLOUT");
    //wvbrowser.loadUrl("http://www.google.com");
    wvbrowser.loadUrl("javascript:window.HTMLOUT.showHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");


    txtcode=(TextView)findViewById(R.id.txtcode);
    txtcode.addTextChangedListener(this);

    btcode=(ImageButton)findViewById(R.id.btcode);
    btcode.setOnClickListener(this);

    }

public void onClick(View v)
{
    if(btgo==v)
    {
        String url=txturl.getText().toString();
        if(!txturl.getText().toString().contains("http://"))
        {
            url="http://"+url;
        }
        wvbrowser.loadUrl(url);
        //wvbrowser.loadData("<html><head></head><body><div style='width:100px;height:100px;border:1px red solid;'></div></body></html>","text/html","utf-8");
    }
    else if(btcode==v)
    {
        ViewGroup.LayoutParams params1=wvbrowser.getLayoutParams();
        ViewGroup.LayoutParams params2=txtcode.getLayoutParams();
        if(flagbtcode==1)
        {
            params1.height=200;
            params2.height=220;
            flagbtcode=0;
            //txtcode.setText(wvbrowser.getContentDescription());
        }
        else
        {
            params1.height=420;
            params2.height=0;
            flagbtcode=1;
        }
        wvbrowser.setLayoutParams(params1);
        txtcode.setLayoutParams(params2);

    }
}

public class HelloWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

        view.loadUrl(url);
        return true;
    }
    /*@Override
    public void onPageFinished(WebView view, String url)
    {
        // This call inject JavaScript into the page which just finished loading. 
        wvbrowser.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
    }*/

}
class MyJavaScriptInterface
{
    @SuppressWarnings("unused")
    public void showHTML(String html)
    {

        txtcode.setText(html);
    }
}

public void afterTextChanged(Editable s) {
    // TODO Auto-generated method stub

}

public void beforeTextChanged(CharSequence s, int start, int count,
        int after) {
    // TODO Auto-generated method stub

}

public void onTextChanged(CharSequence s, int start, int before, int count) {
    wvbrowser.loadData("<html><div"+txtcode.getText().toString()+"></div></html>","text/html","utf-8");

}

}

Ответы [ 12 ]

102 голосов
/ 20 ноября 2011

На самом деле этот вопрос имеет много ответов. Вот 2 из них:

  • Это первое почти то же самое, что и у вас, я думаю, что мы получили его из того же урока.

public class TestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.webview);
        final WebView webview = (WebView) findViewById(R.id.browser);
        webview.getSettings().setJavaScriptEnabled(true);
        webview.addJavascriptInterface(new MyJavaScriptInterface(this), "HtmlViewer");

        webview.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                webview.loadUrl("javascript:window.HtmlViewer.showHTML" +
                        "('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
            }
        });

        webview.loadUrl("http://android-in-action.com/index.php?post/" +
                "Common-errors-and-bugs-and-how-to-solve-avoid-them");
    }

    class MyJavaScriptInterface {

        private Context ctx;

        MyJavaScriptInterface(Context ctx) {
            this.ctx = ctx;
        }

        public void showHTML(String html) {
            new AlertDialog.Builder(ctx).setTitle("HTML").setMessage(html)
                    .setPositiveButton(android.R.string.ok, null).setCancelable(false).create().show();
        }

    }
}

Таким образом, вы можете получить HTML через JavaScript. Не самый красивый способ, но когда у вас есть свой интерфейс javascript, вы можете добавить другие методы, чтобы повозиться с ним.


  • Другой способ - использовать HttpClient, например там .

Выбор, который вы выбираете, также зависит, я думаю, от того, что вы намереваетесь делать с найденным html ...

40 голосов
/ 27 марта 2013

Для Android 4.2, не забудьте добавить @JavascriptInterface ко всем функциям JavaScript

38 голосов
/ 17 августа 2015

В KitKat и выше вы можете использовать evaluateJavascript метод для веб-просмотра

wvbrowser.evaluateJavascript(
        "(function() { return ('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>'); })();",
         new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String html) {
                Log.d("HTML", html); 
                // code here
            }
    });

См. этот ответ для дополнительных примеров

10 голосов
/ 08 марта 2012

Android WebView - это просто еще один механизм рендеринга, который отображает содержимое HTML, загруженное с HTTP-сервера, во многом подобно Chrome или FireFox.Я не знаю причину, почему вам нужно получить отрендеренную страницу (или скриншот) из WebView.В большинстве случаев это не обязательно.Вы всегда можете получить необработанный HTML-контент напрямую с HTTP-сервера.

Уже опубликованы ответы, в которых говорится о получении необработанного потока с помощью HttpUrlConnection или HttpClient.В качестве альтернативы, есть очень удобная библиотека для анализа / обработки HTML-контента на Android: JSoup , она предоставляет очень простой API для получения HTML-контента с HTTP-сервера и предоставляет абстрактное представление HTML-документа, чтобы помочьмы управляем синтаксическим анализом HTML не только в более OO-стиле, но и намного проще:

// Single line of statement to get HTML document from HTTP server.
Document doc = Jsoup.connect("http://en.wikipedia.org/").get();

Это удобно, когда, например, вы хотите сначала загрузить документ HTML, а затем добавить в него несколько пользовательских CSS или JavaScriptпередавая его в WebView для рендеринга.Многое на официальном сайте, стоит проверить.

5 голосов
/ 13 января 2013

Одна точка касания, которую я обнаружил и которую нужно поставить на место, «скрыта» в конфигурации Proguard.Несмотря на то, что программа чтения HTML-файлов прекрасно запускается через интерфейс javascript при отладке приложения, это больше не работает, как только приложение запускается через Proguard, если только функция чтения HTML не объявлена ​​в файле конфигурации Proguard, например:1002 *

Протестировано и подтверждено на Android 2.3.6, 4.1.1 и 4.2.1.

4 голосов
/ 18 февраля 2012

Android не позволит вам сделать это из соображений безопасности.Злой разработчик может очень легко украсть введенную пользователем информацию для входа в систему.

Вместо этого вам нужно поймать текст, отображаемый в веб-представлении, прежде чем он отобразится.Если вы не хотите настраивать обработчик ответа (как и в других ответах), я нашел это исправление с некоторым поиском в Google:

URL url = new URL("https://stackoverflow.com/questions/1381617");
URLConnection con = url.openConnection();
Pattern p = Pattern.compile("text/html;\\s+charset=([^\\s]+)\\s*");
Matcher m = p.matcher(con.getContentType());
/* If Content-Type doesn't match this pre-conception, choose default and 
 * hope for the best. */
String charset = m.matches() ? m.group(1) : "ISO-8859-1";
Reader r = new InputStreamReader(con.getInputStream(), charset);
StringBuilder buf = new StringBuilder();
while (true) {
  int ch = r.read();
  if (ch < 0)
    break;
  buf.append((char) ch);
}
String str = buf.toString();

Это много кода, и вы должны иметь возможностьскопируйте / вставьте его, и в конце его str будет содержать тот же HTML-код, нарисованный в веб-просмотре.Этот ответ от Самый простой способ правильно загрузить HTML с веб-страницы в строку в Java , и это должно работать и на Android.Я не проверял это и не писал сам, но это может вам помочь.

Кроме того, URL-адрес, который он запрашивает, жестко запрограммирован, поэтому вам придется его изменить.

1 голос
/ 17 марта 2012

Я бы предложил вместо того, чтобы пытаться извлечь HTML из WebView, вы извлекаете HTML из URL. Под этим я подразумеваю использование сторонней библиотеки, такой как JSoup, для просмотра HTML для вас. Следующий код получит HTML-код с определенного URL-адреса для вас

public static String getHtml(String url) throws ClientProtocolException, IOException {
        HttpClient httpClient = new DefaultHttpClient();
        HttpContext localContext = new BasicHttpContext();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response = httpClient.execute(httpGet, localContext);
        String result = "";

        BufferedReader reader = new BufferedReader(
            new InputStreamReader(
                response.getEntity().getContent()
            )
        );

        String line = null;
        while ((line = reader.readLine()) != null){
            result += line + "\n";
        }
        return result;
    }
1 голос
/ 06 марта 2012

Почему бы сначала не получить html, а затем передать его в веб-представление?

private String getHtml(String url){
    HttpGet pageGet = new HttpGet(url);

    ResponseHandler<String> handler = new ResponseHandler<String>() {
        public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
            HttpEntity entity = response.getEntity();
            String html; 

            if (entity != null) {
                html = EntityUtils.toString(entity);
                return html;
            } else {
                return null;
            }
        }
    };

    pageHTML = null;
    try {
        while (pageHTML==null){
            pageHTML = client.execute(pageGet, handler);
        }
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return pageHTML;
}

@Override
public void customizeWebView(final ServiceCommunicableActivity activity, final WebView webview, final SearchResult mRom) {
    mRom.setFileSize(getFileSize(mRom.getURLSuffix()));
    webview.getSettings().setJavaScriptEnabled(true);
    WebViewClient anchorWebViewClient = new WebViewClient()
    {

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);

            //Do what you want to with the html
            String html = getHTML(url);

            if( html!=null && !url.equals(lastLoadedURL)){
                lastLoadedURL = url;
                webview.loadDataWithBaseURL(url, html, null, "utf-8", url);
            }
}

Это должно примерно сделать то, что вы хотите.Он адаптирован с Возможно ли получить HTML-код из WebView и выкрикнуть https://stackoverflow.com/users/325081/aymon-fournier за ответ.

0 голосов
/ 15 марта 2012

Предлагаю опробовать подход Reflection, если у вас есть время потратить на отладчик (извините, но у меня не было).

Начиная с метода loadUrl() класса android.webkit.WebView:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/webkit/WebView.java#WebView.loadUrl%28java.lang.String%2Cjava.util.Map%29

Вы должны получить android.webkit.BrowserFrame, который вызывает nativeLoadUrl() собственный метод:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/webkit/BrowserFrame.java#BrowserFrame.nativeLoadUrl%28java.lang.String%2Cjava.util.Map%29

Реализация нативного метода должна быть здесь:

http://gitorious.org/0xdroid/external_webkit/blobs/a538f34148bb04aa6ccfbb89dfd5fd784a4208b1/WebKit/android/jni/WebCoreFrameBridge.cpp

Желаю удачи!

0 голосов
/ 11 марта 2012

Это просто для реализации Просто нужно javasript методы в вашем html, чтобы получить значение содержимого html. Как и в вашем коде, необходимо внести некоторые изменения.

  public class htmldecoder extends Activity implements OnClickListener,TextWatcher
    {
    Button btsubmit; // this button in your xml file
    WebView wvbrowser;
    public void onCreate(Bundle savedInstanceState)
    {
                super.onCreate(savedInstanceState);
                    setContentView(R.layout.htmldecoder);



        btsubmit=(Button)findViewById(R.id.btsubmit);
        btsubmit.setOnClickListener(this);

        wvbrowser=(WebView)findViewById(R.id.wvbrowser);
        wvbrowser.setWebViewClient(new HelloWebViewClient());
        wvbrowser.getSettings().setJavaScriptEnabled(true);
        wvbrowser.getSettings().setPluginsEnabled(true);
        wvbrowser.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        MyJavaScriptInterface myinterface=new MyJavaScriptInterface();
        wvbrowser.addJavascriptInterface(myinterface,"interface");
        webView.loadUrl("file:///android_asset/simple.html");  //use one html file for //testing put your html file in assets. Make sure that you done JavaScript methods to get //values for html content in html file . 
   }
   public void onClick(View v)
{
    if(btsubmit==v)
    {

        webView.loadUrl("javascript:showalert()");// call javascript method.  
        //wvbr
    }
}

final class MyJavaScriptInterface {



        MyJavaScriptInterface() {

        }

        public void sendValueFromHtml(String value) {
           System.out.println("Here is the value from html::"+value);
        }

    }

}

Ваш Javascript в HTML

 <script type="text/javascript">
    //<![CDATA[
    var n1;
    function callme(){
    n1=document.getElementById("FacadeAL").value;
    }
    function showalert(){
     window.interface.sendValueFromHtml(n1);// this method calling the method of interface which //you attached to html file in android. // & we called this showalert javasript method on //submmit buttton click of android. 
    }
    //]]>
    </script>

& Убедитесь, что вы вызываете callme, как показано ниже в html

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
Надеюсь, это поможет вам.

...