WebView通常用于加载某个网页,如下
mWebView.loadUrl(mUrl);
然而在有些情况下,我们只需加载网页的某一部分,而非全部。如新闻页只需加载标题和正文,而摒弃广告、侧边栏等。如何解决这个问题呢?
接下来我们将从以下四个步骤展开:
以上步骤分别对应四个模块:Crawler、Parser、Renderer、Loader
在Crawler和Parser中,涉及到一款重要的工具——Jsoup
Jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
具体可参考官网:http://jsoup.org/
接下来,将从代码层面依次描述以上各模块的实现。
先给出总体框架:
public void loadRemotePage(String url) {
WebPageTransformer.transform(url, new IWebPageTransformer() {
@Override
public void onPageTransform(String content) {
// TODO Auto-generated method stub
loadLocalPage(content);
}
});
}
public class WebPageTransformer {
public static interface IWebPageTransformer {
public void onPageTransform(String content);
}
public static void transform(final String url, final IWebPageTransformer transformer) {
AsyncTaskUtils.execute(new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
Document doc = ArticleCrawler.crawlWebPage(url);
Article article = ArticleParser.parseArticle(doc);
return ArticleRender.render(article);
}
@Override
protected void onPostExecute(String html) {
// TODO Auto-generated method stub
if (transformer != null) {
transformer.onPageTransform(html);
}
}
});
}
}
接下来是Crawler,功能很简单,用get方式抓取指定url的html,如下
public class ArticleCrawler {
public static Document crawlWebPage(String url) {
try {
Document document = Jsoup.connect(url)
.userAgent("Mozilla").get();
return document;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
然后是Parser,用于抽取Crawler所得到的网页Html中感兴趣的标签,生成本地数据结构
public class ArticleParser {
public static Article parseArticle(Document doc) {
Article article = new Article();
Element titleElem = doc.getElementById("artical_topic");
if (titleElem != null) {
Title title = new Title();
title.setText(titleElem.text());
article.addElementRender(title);
}
Elements elements = doc.select("div#main_content p");
for (Element element : elements) {
if (element.hasClass("detailPic")) {
Elements images = element.select("img");
String src = images.get(0).attr("src");
if (!TextUtils.isEmpty(src)) {
Image image = new Image();
image.setUrl(src);
image.setImageSize();
article.addElementRender(image);
}
} else {
Span span = new Span();
span.setText(element.text());
article.addElementRender(span);
}
}
return article;
}
}
接下来该由Renderer渲染本地数据结构,生成本地Html
public class ArticleRender {
public static String render(Article article) {
StringBuilder sb = new StringBuilder();
List<ElementRender> renders = article.getElementRenders();
for (ElementRender render : renders) {
sb.append(render.getRenderHtml());
}
return sb.toString();
}
}
最后,由WebView加载渲染后的本地Html即可
public void loadLocalPage(String content) {
String template = CommonUtils.getFileFromAssets(mContext, "newscont.html");
template = template.replace("{{template_content}}", content);
template = template.replace("{{webview_width}}", "" + CommonUtils.getScreenWidthIntPx());
template = template.replace("{{webview_height}}", "" + CommonUtils.getScreenHeightIntPx());
loadDataWithBaseURL("file:///android_asset/", template, "text/html", "UTF-8", null);
}
总体基本上就是这些,然而还有诸多细节,如图片如何加载,本地html样式如何调整等问题我们后面再讨论。