как получить html-контент из веб-просмотра?

123

Какой самый простой способ получить 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");

}

}
Hope4You
источник

Ответы:

107

Собственно на этот вопрос есть много ответов. Вот 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 ...

Sephy
источник
при выполнении этой строки webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");программа действует как функция finish () и останавливает это действие. почему? как это решить?
7
webview.addJavascriptInterface работает только с Jelly Beans и более ранними версиями.
xtr
32
Два важных изменения в приведенном выше коде для Jellybean и более поздних версий: 1. Удаление «окна». из строки webview.loadUrl - интерфейс javascript подключается по-другому при настройке Jellybean. 2. Поместите @JavascriptInterface перед «public void showHTML» - это необходимо, поскольку не разрешать только вызов определенных методов - угроза безопасности.
karlbecker_com
1
У меня все еще не работает (5.1.1) .. Когда я добавляю MyJavaScriptInterface (с подсказками @karlbecker_com), когда я нажимаю что-то на загруженной странице, система просит меня выбрать браузер. Когда я удалю это, меня больше не спросят.
Makalele 03 окт.15,
1
Здесь я включил удаленную отладку, она показывала Uncaught ReferenceError: HtmlViewer is not defined, независимо от того, есть они или нет@JavascriptInterface
MewX
55

В 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
            }
    });

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

Акаш Куриан Хосе
источник
это, безусловно, самое простое решение для использования здесь
Билли
9
FYI - Требуется API 19.
Джоэл
7
Не забудьте поместить это в метод onPageFinished.
Седрик Портманн
@Joel Как этого добиться ниже API 19?
Pratik Saluja,
1
@PratikSaluja извините, если мой комментарий передал неправильную идею. Ответ с большинством голосов здесь намного старше моего собственного и, вероятно, сработает для вас. Больше ничего не значило. Очень рад, что вы нашли ответ, поискав в другом месте, кстати.
Акаш Куриан Хосе,
41

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

user1842354
источник
1
Работает на android 4.2 и выше.
Седрик Портманн
10

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 для рендеринга. Гораздо больше на их официальном веб-сайте, стоит посмотреть.

yorkw
источник
5

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

-keepclassmembers class <your.fully.qualified.HTML.reader.classname.here> {
    public *; 
}

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

user1756541
источник
4

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

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

URL url = new URL("/programming/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-адрес жестко запрограммирован, поэтому вам придется его изменить.

edthethird
источник
1

Почему бы не получить сначала 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 .

Карл Л
источник
HttpClient объявлен устаревшим на уровне API 22 и удален на уровне API 23. Таким образом, классы, упомянутые в вашем коде, не могут быть импортированы в файлы java.
Dhananjay M
1

Я бы предложил вместо того, чтобы пытаться извлечь 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;
    }
Mimminito
источник
Предположим, получение URL-адреса достигается путем публикации данных. этот метод не сработает.
Джафар Али
А как насчет файлов cookie?
Кейт Адлер,
0

Его просто реализовать Просто нужны методы 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()"/>
Надеюсь, что это поможет вам.

Г-н Саджид Шейх
источник
что это значит. & Make sure you calling callme like below in htmlВы хотели разместить тег ввода под скриптом в html файле? Thank You
Нет, чувак, тебе нужно вызвать метод javasript callme () onblur текста типа ввода в теге html.
Г-н Саджид Шейх
тогда куда добавить этот входной тег. Видна ли эта кнопка?
этот код работает так, как при загрузке активности есть текстовое поле в веб-просмотре, а набранный текст отображается в текстовом поле. Но я хочу, чтобы html-код в веб-просмотре.
вы можете помочь мне разобраться с этой проблемой? Thank you very much
0

Я предлагаю попробовать какой-нибудь подход 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

Удачи!

lechuckcaptain
источник
-1

попробуйте использовать HttpClient, как сказал Сефи:

public String getHtml(String url) {
    HttpClient vClient = new DefaultHttpClient();
    HttpGet vGet = new HttpGet(url);
    String response = "";    

    try {
        ResponseHandler<String> vHandler = new BasicResponseHandler();
        response = vClient.execute(vGet, vHandler);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return response;
}
Кристопер Ганс
источник
Можете ли вы показать простой рабочий пример.
Я
этот метод получит исходный HTML-код данного URL-адреса. т.е. getHtml ( google.com ); предоставит вам исходный код главной страницы Google
Christoper Hans
это нормально. есть ли возможность получить источник веб-просмотра. THANKS
KIRAN KJ
Это несколько не сработало для меня. Я не получал никакого контента с тестового сайта, содержание которого было бы "hello world".
Momro 06
-2

Приведенные выше методы предназначены для того, если у вас есть веб-адрес, но если у вас есть локальный html, вы также можете иметь html с помощью этого кода

AssetManager mgr = mContext.getAssets();
             try {
InputStream in = null;              
if(condition)//you have a local html saved in assets
                            {
                            in = mgr.open(mFileName,AssetManager.ACCESS_BUFFER);
                           }
                            else if(condition)//you have an url
                            {
                            URL feedURL = new URL(sURL);
                  in = feedURL.openConnection().getInputStream();}

                            // here you will get your html
                 String sHTML = streamToString(in);
                 in.close();

                 //display this html in the browser or web view              


             } catch (IOException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
             }
        public static String streamToString(InputStream in) throws IOException {
            if(in == null) {
                return "";
            }

            Writer writer = new StringWriter();
            char[] buffer = new char[1024];

            try {
                Reader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));

                int n;
                while ((n = reader.read(buffer)) != -1) {
                    writer.write(buffer, 0, n);
                }

            } finally {

            }

            return writer.toString();
        }
Vipin
источник