jak uzyskać zawartość html z widoku internetowego?


123

Jaka jest najprostsza metoda uzyskania kodu HTML z widoku internetowego? Wypróbowałem kilka metod ze stackoverflow i google, ale nie mogę znaleźć dokładnej metody. Podaj dokładny sposób.

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");

}

}

Odpowiedzi:


107

Właściwie to pytanie ma wiele odpowiedzi. Oto 2 z nich:

  • Ten pierwszy jest prawie taki sam jak twój, myślę, że uzyskaliśmy go z tego samego samouczka.

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

    }
}

W ten sposób pobierzesz html za pomocą javascript. Nie jest to najładniejszy sposób, ale kiedy masz interfejs javascript, możesz dodać inne metody, aby go majstrować.


  • Innym sposobem jest użycie HttpClient, jak tam .

Myślę, że opcja, którą wybierzesz, zależy również od tego, co zamierzasz zrobić z pobranym html ...


po wykonaniu tej linii webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");program zachowuje się jak funkcja finish () i zatrzymuje tę czynność. dlaczego? jak to rozwiązać?

7
webview.addJavascriptInterface Działa tylko na Jelly Beans i niższych wersjach.
xtr

32
Dwie ważne zmiany w powyższym kodzie dla Jellybean i nowszych: 1. Usuń „window”. z wiersza webview.loadUrl - interfejs javascript jest dołączany inaczej podczas kierowania na Jellybean. 2. Umieść @JavascriptInterface przed "public void showHTML" - jest to konieczne, ponieważ zezwalanie na wywoływanie niektórych metod jest zagrożeniem dla bezpieczeństwa.
karlbecker_com

1
Nadal nie działa dla mnie (5.1.1) .. Kiedy dodaję MyJavaScriptInterface (z podpowiedziami @karlbecker_com), kiedy klikam coś na załadowanej stronie, system prosi mnie o wybranie przeglądarki. Kiedy to usunę, nie będzie mnie więcej pytać.
Makalele

1
Tutaj włączyłem zdalne debugowanie, pokazało Uncaught ReferenceError: HtmlViewer is not defined, nieważne z czy bez@JavascriptInterface
MewX

55

W KitKat i nowszych evaluateJavascriptwersjach można użyć metody w widoku sieci Web

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

Zobacz odpowiedź, aby uzyskać więcej przykładów


jest to zdecydowanie najłatwiejsze rozwiązanie tutaj
Billy

9
Do Twojej wiadomości - wymaga API 19.
Joel

7
Pamiętaj, aby umieścić to w metodzie onPageFinished.
Cédric Portmann

@Joel Jak to osiągnąć poniżej API 19?
Pratik Saluja

1
@PratikSaluja bardzo przepraszam, jeśli mój komentarz zawierał zły pomysł. Odpowiedź z większością głosów za jest znacznie starsza niż moja własna odpowiedź i prawdopodobnie zadziała dla Ciebie. Nic poza tym nie znaczyło. Bardzo się cieszę, że znalazłeś odpowiedź, szukając gdzie indziej.
Akash Kurian Jose


10

Android WebView to kolejny silnik renderujący, który renderuje zawartość HTML pobraną z serwera HTTP, podobnie jak Chrome czy FireFox. Nie wiem, dlaczego potrzebujesz wyrenderowanej strony (lub zrzutu ekranu) z WebView. W większości sytuacji nie jest to konieczne. Zawsze możesz pobrać surową zawartość HTML bezpośrednio z serwera HTTP.

Istnieją już odpowiedzi na temat pobierania surowego strumienia przy użyciu HttpUrlConnection lub HttpClient. Alternatywnie, istnieje bardzo przydatna biblioteka do zajmowania się analizą / procesem treści HTML na Androidzie: JSoup , zapewnia bardzo proste API do pobierania treści HTML z serwera HTTP i zapewnia abstrakcyjną reprezentację dokumentu HTML, aby pomóc nam zarządzać analizowaniem HTML nie tylko w stylu bardziej OO, ale także znacznie łatwiej:

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

Jest to przydatne, gdy na przykład chcesz najpierw pobrać dokument HTML, a następnie dodać do niego niestandardowy css lub javascript przed przekazaniem go do WebView w celu renderowania. Znacznie więcej na ich oficjalnej stronie internetowej, warto to sprawdzić.


5

Odkryłem, że jeden punkt dotykowy, który należy wprowadzić, jest „ukryty” w konfiguracji Proguard. Podczas gdy czytnik HTML wywołuje interfejs javascript dobrze podczas debugowania aplikacji, nie działa to już, gdy aplikacja zostanie uruchomiona przez Proguard, chyba że funkcja czytnika HTML jest zadeklarowana w pliku konfiguracyjnym Proguard, na przykład:

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

Przetestowane i potwierdzone na Androidzie 2.3.6, 4.1.1 i 4.2.1.


4

Android nie pozwoli ci tego zrobić ze względów bezpieczeństwa. Zły programista może bardzo łatwo ukraść dane logowania wprowadzone przez użytkownika.

Zamiast tego musisz przechwycić tekst wyświetlany w widoku sieci Web, zanim zostanie wyświetlony. Jeśli nie chcesz konfigurować modułu obsługi odpowiedzi (zgodnie z innymi odpowiedziami), znalazłem tę poprawkę przy użyciu googlowania:

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();

To dużo kodu i powinieneś być w stanie go skopiować / wkleić, a na końcu strbędzie zawierał ten sam html narysowany w widoku WWW. Ta odpowiedź pochodzi z najprostszego sposobu, aby poprawnie załadować html ze strony internetowej do ciągu znaków w Javie i powinna działać również na Androidzie. Nie testowałem tego i nie napisałem tego sam, ale może ci to pomóc.

Ponadto pobierany przez to adres URL jest zakodowany na stałe, więc musisz to zmienić.


1

Dlaczego nie pobrać najpierw kodu HTML, a następnie przekazać go do widoku internetowego?

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

Powinno to z grubsza zrobić to, co chcesz. Jest zaadaptowany z Czy można pobrać kod HTML z WebView i krzyczeć na https://stackoverflow.com/users/325081/aymon-fournier, aby uzyskać odpowiedź.


HttpClient został wycofany na poziomie interfejsu API 22 i usunięty na poziomie interfejsu API 23. Dlatego klas wymienionych w kodzie nie można zaimportować do plików java.
Dhananjay M

1

Sugerowałbym, aby zamiast próbować wyodrębnić kod HTML z WebView, wyodrębnić HTML z adresu URL. Rozumiem przez to użycie biblioteki innej firmy, takiej jak JSoup, do przeglądania HTML za Ciebie. Poniższy kod pobierze kod HTML z określonego adresu 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;
    }

załóżmy, że uzyskanie adresu URL jest osiągane przez publikowanie danych. ta metoda zawiedzie.
Jafar Ali

A co z ciasteczkami?
Keith Adler

0

Jego prosta implementacja Wystarczy, że użyjesz metod javasript w swoim html, aby uzyskać wartość treści html. Jak nad kodem, trzeba będzie wprowadzić pewne zmiany.

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

    }

}

Twój JavaScript w 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>

& Upewnij się, że dzwonisz do callme jak poniżej w html

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
Mam nadzieję, że to ci pomoże.


co to znaczy. Czy & Make sure you calling callme like below in htmlchodziło Ci o umieszczenie znacznika wejściowego poniżej skryptu w pliku html? Thank You

nie koleś, musisz wywołać metodę javasript callme () onblur typu input w tagu html.
Pan Sajid Shaikh

gdzie dodać ten znacznik wejściowy. czy ten przycisk jest widoczny?

ten kod działa tak, jak podczas ładowania aktywności w widoku sieciowym znajduje się pole tekstowe, a wpisany tekst jest wyświetlany w polu tekstowym. Ale chcę, aby kod HTML był w widoku sieciowym.

czy możesz mi pomóc rozwiązać ten problem? Thank you very much

0

-1

spróbuj użyć HttpClient, jak powiedziała Sephy:

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

czy możesz pokazać prosty działający przykład. nie mogę zaimplementować kodu w przykładzie
Sephy

ta metoda pobierze źródło html podanego adresu URL. tj. getHtml ( google.com ); znajdzie źródło strony głównej google
Christoper Hans

jest ok. czy jest jakaś opcja, aby uzyskać źródło Webview. THANKS
KIRAN KJ

To trochę mi nie pomogło. Nie otrzymałem żadnej treści z witryny testowej, której treść była „witaj świecie”.
Momro

-2

powyższe metody są dla jeśli masz adres URL, ale jeśli masz lokalny html, możesz również mieć html za pomocą tego kodu

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();
        }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.