【问题标题】:How to get the HTML of shown content in Webview如何在 Webview 中获取显示内容的 HTML
【发布时间】:2016-09-21 16:08:23
【问题描述】:

出于教育原因,我正在学习解析和抓取 HTML 内容。 我看到了很多关于检索 webview 中显示的 html 内容的问题和答案。 我的问题是,我无法获得整个 html,我认为它应该是什么样子。当我在 Safari 中检查 URL 时,所有项目都可以位于 HTML 中,但是当我从 webview 加载相同 URL 的 HTML 时,缺少项目。 我现在的代码: `

private WebView wv;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);

    wv = (WebView) findViewById(R.id.webView);
    wv.getSettings().setJavaScriptEnabled(true);

    wv.addJavascriptInterface(new LoadListener(), "HTMLOUT");
}

@Override
protected void onStart() {
    super.onStart();

    wv.setWebViewClient(new WebViewClient() {
        public void onPageFinished(WebView view, String url) {
            if(wv.getProgress() == 100) {
                view.loadUrl("javascript:window.HTMLOUT.processHTML(document.documentElement.innerHTML);");
            }
        }
    });


    wv.loadUrl("http://hdfilme.tv/movie-movies?order_f=view&order_d=desc&per_page=#");
}

class LoadListener{
    @JavascriptInterface
    public void processHTML(String html) {
        longInfo(html);
    }
}

public static void longInfo(String str) {
    if (str.length() > 4000) {
        Log.i("DEBUG", str.substring(0, 4000));
        longInfo(str.substring(4000));
    } else
        Log.i("DEBUG", str);
}`

通常我使用 Jsoup 连接和解析 HTML,但在这种情况下,网页使用 CloudFlare,我无法成功加载页面 HTML。

我发现包含<span class="hot"></span>标签的网页的每个Listitem现在都没有加载到我的代码中。

我错过了什么?

更新1

F.Klein 的暗示做到了!

我真的不明白为什么要设置用户代理如下: wv.getSettings().setUserAgentString("Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13");

按照我的设想更改了检索到的 HTML。 webview中显示的内容在设置用户代理之前和之后都是一样的。

UPDATE2

我一直很高兴...更改用户代理最终导致缺少要显示的项目,但是之前加载的其他项目现在消失了???我不明白这个问题。

【问题讨论】:

  • 您是否尝试过设置用户代理?默认会加载移动演示文稿,版本可能存在差异。
  • 还没有,我试试看。提前致谢。
  • 返回的HTML中缺少的项目显示在Webview中,这就是我如此困惑的原因,但我会尝试设置一个用户代理。
  • onPageFinished() 不考虑 AJAX,因此您可能会在整个内容加载之前调用它。
  • 我尝试延迟 5 秒,但没有帮助。我在加载的 HTML 中缺少的内容已经在 webview 中可见,因此这不应该是问题。

标签: javascript android html webview jsoup


【解决方案1】:

如前所述,页面的移动版本似乎与默认版本不同:移动版本有 50 个 divelements 与 box-productfound 类,而默认版本找到 70 个元素。

修复

String userAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36";
wv.getSettings().setUserAgentString(userAgent);

您提到的用户代理(更新 1)是用于移动版本的,因此与未设置用户代理的结果相同(默认为 android 上的移动版本)。


不使用 WebView 的替代方案使用Rhino(计算获取访问 cookie 的挑战):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    new BackgroundTask().execute();

}

class BackgroundTask extends AsyncTask<Void,Void,Void>{

    @Override
    protected Void doInBackground(Void... voids) {
        scrapePage();
        return null;
    }
}

private void scrapePage() {

    Map<String, String> cookies;
    final String referrer = "http://hdfilme.tv/movie-movies?order_f=view&order_d=desc&per_page=0";

    try {

        Connection.Response res = Jsoup.connect("http://hdfilme.tv/movie-movies?order_f=view&order_d=desc&per_page=#")
                .followRedirects(true).header("Connection", "keep-alive").userAgent(userAgent)
                .ignoreHttpErrors(true).header("host", "hdfilme.tv").referrer(referrer).method(Connection.Method.GET)
                .execute();

        cookies = res.cookies();

        Document doc = Jsoup.parse(res.body());

        String[] scriptlines = doc.select("script").toString().split("\n");

        StringBuilder builder = new StringBuilder();
        builder.append("var a={};");

        for (String line : scriptlines) {
            if (line.contains("var s,t,o,p,b,r,e,a,k,i,n,g")) {
                builder.append(line.trim());
                builder.append("t=\"hdfilme.tv\"");
            }
            if (line.contains("a.value = parseInt")) {
                builder.append(line.trim());
            }
        }

        int jschl_answer = runRhino(builder.toString());
        String jschl_vc = doc.select("input[name=jschl_vc]").first().attr("value");
        String pass = doc.select("input[name=pass]").first().attr("value");

        Log.e("info","Acquiring access cookies (takes about 4 seconds).");

        try {
            Thread.sleep(4000); //DDOS protection
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        String requestUrl = "http://hdfilme.tv/cdn-cgi/l/chk_jschl";

        res = Jsoup.connect(requestUrl).followRedirects(true).userAgent(userAgent)
                .header("Referer", "http://hdfilme.tv/movie-movies?order_f=view&order_d=desc&per_page=")
                .data("jschl_vc", jschl_vc).ignoreHttpErrors(true).cookies(cookies)
                .data("jschl_answer", "" + jschl_answer).data("pass", pass).header("host", "hdfilme.tv")
                .method(Connection.Method.GET).timeout(5000).execute();

        Log.e("repsonse",res.statusCode() + " - " + res.statusMessage());

        cookies.putAll(res.cookies());

        builder = new StringBuilder();
        builder.append("\tcookies");
        for (String cookie : cookies.keySet()) {
            builder.append("\n\t\t" + cookie + ":" + cookies.get(cookie));
        }

        Log.e("cookies", builder.toString());

        doc = Jsoup.connect("http://hdfilme.tv/movie-movies?order_f=view&order_d=desc&per_page=#")
                .cookies(cookies)
                .userAgent(userAgent)
                .timeout(10000).referrer(referrer).header("host", "hdfilme.tv").followRedirects(true).get();

        builder = new StringBuilder();
        builder.append("elements");

        for (Element element : doc.select(selector)) {
            builder.append("\n"+element.select("a[href]").attr("abs:href"));
        }

        Log.e("elements","total number of elements="+doc.select(selector).size()+"\n"+builder.toString());

    } catch (IOException e) {
        e.printStackTrace();
    }
}

private int runRhino(String jsSource) {
    Context rhino = Context.enter(); // org.mozilla.javascript.Context;

    // Turn off optimization to make Rhino Android compatible
    rhino.setOptimizationLevel(-1);

    Scriptable scope = rhino.initStandardObjects();
    rhino.evaluateString(scope, jsSource, "ScriptAPI", 1, null);

    NativeObject object = (NativeObject) scope.get("a", scope);
    return (int) ((Double) object.get("value") / 1);
}

【讨论】:

    猜你喜欢
    • 2012-01-02
    • 2014-09-04
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多