在Android开发中经常需要获取各种各样的数据,若服务器没有数据或者懒得去收集数据,这时候不妨采用Jsoup抓取各大网站的数据;若需要加载大量图片,想必也是个头疼的地方,这时候不妨使用universal-image-loader(图片加载框架);当然我们真正抓取的知识简单标题和URL链接,所有这时候还需要内置WebView用来显示正文。下面,我们就结合RollViewPage来如下功能。
这是要抓取的网页:
这是效果:
Jsoup的使用
要去爬别人的 HTML 标签的话,首先你肯定得有一定的 HTML 的基础知识吧。比如说常用的标签,标签的相关属性,这个就不多说了,有相关问题都可以在 www.w3school.com.cn 的网站解决一下。
准备
使用之前需要先导入Jsoup(源码有)
详解
目标Html代码:
<div id="da-slider" class="da-slider">
<div class="da-slide">
<h2>沟通表达 Tiny EMaG</h2>
<p> 你和理想的学校之间,只差一场EMaG ~
面试礼仪 || 沟通表达
问答技巧 || 演讲训练
社交技能 || 思维逻辑
……
表达一门永无止境的艺术</p>
<a href="http://www.educubeglobal.com/master/get_notice_by_id/55" target="_blank" class="da-link">More</a>
<div class="da-img"> <img src="/application/script/kindeditor-4.1.4/attached/image/20150430/20150430145125_26612.jpg" alt="EmaG" /></div>
</div>
<div class="da-slide">
<h2>台湾深度探访营~新一代背包客</h2>
<p> 学立方新一代背包客,走进台湾,开创个人亲身体验的“我学我立,方成长”的一种超越时空、文化与科技的学习方法,走一段非比寻常的闽台文化交流之旅。</p>
<a href="http://www.educubeglobal.com/master/teenager" target="_blank" class="da-link">More</a>
<div class="da-img"> <img src="/application/script/kindeditor-4.1.4/attached/image/20140527/20140527170608_48705.jpg" alt="EmaG" /></div>
</div>
<div class="da-slide">
<h2>学立方百英计划</h2>
<p> 百炼成钢,英才辈出!学立方2014素质拓展夏令营,在这里,我们学习有方法,成长有素质,生活有文化,在快乐中为下学年的学习创造健康扎实的基础。</p>
<a href="http://www.educubeglobal.com/master/teenager" target="_blank" class="da-link">More</a>
<div class="da-img"> <img src="/application/script/kindeditor-4.1.4/attached/image/20140528/20140528110147_89047.jpg" alt="EmaG" /></div>
</div>
<div class="da-slide">
<h2>台湾夏令营~新一代背包客4.0</h2>
<p> 从领袖训练到英语学习、从校园体验到田园知趣、 从夜市到故宫、从人性到文化、从台北101到南投日月潭, 多方促进海峡两岸青少年交流,增进双方友谊,深入了解台湾, 加入学立方夏令营,您将有难忘的学习交流经验与美好的回忆。</p>
<a href="http://www.educubeglobal.com/CSPDM/" target="_blank" class="da-link">了解更多</a>
<div class="da-img"> <img src="/application/script/kindeditor-4.1.4/attached/image/20130619/20130619154828_13834.png" alt="EmaG" /></div>
</div>
<div class="da-slide">
<h2>学立方素质教育网</h2>
<p> 素质教育的推广与实践,是学立方教育从人本出发的服务核心,旨在锻造在学儿少青年与在职专业人员“双语视野、信息应用、体能体魄、人文通识、沟通领导、社会网络、问题解决与思辨决策”等八项素质能力,采用曾章瑞教授所创建的EMaG模式积极发展。</p>
<a href="http://www.educubeglobal.com/CSPDM" target="_blank" class="da-link">进入网站</a>
<div class="da-img"> <img src="/application/script/kindeditor-4.1.4/attached/image/20131127/20131127173239_20069.jpg" alt="EmaG" /></div>
</div>
<div class="da-slide">
<h2>学立方推出“新一代托管课程”</h2>
<p> 1、辅导并确保完成作业——每天进步一点点! 2、完成作业后转化为趣味休闲: (1)3D影片(动画)展播与互动学习——不一样的学习有不一样的成长。 (2)Asaka姐姐讲故事——精彩持续,激发想象力。 (3)素质训练、益智游戏——智力和素质的同步成长。</p>
<div class="da-img"> <img src="/application/script/kindeditor-4.1.4/attached/image/20130620/20130620163946_67744.jpg" alt="EmaG" /></div>
</div>
<div class="da-arrows"> <span class="da-arrows-prev"></span><span class="da-arrows-next"></span> </div>
</div>
解析Html代码:
(1)审查网页元素后发现,我们要的内容在上面的目标HTML代码中,在整个网页中是在 class=”da-slider” id=”da-slider” 中
(2)标题如“沟通表达 Tiny EMaG<”都在“h2”标签中
(3)需要的图片链接都在 “img”标签中
(4)需要的网页链接都在 “a”标签中,注意这边是在“a”中的“href”
好了,标题、图片链接、网页链接都已经到手,我们可以抓取获取
try {
//创建一个Document对象获取网页内容
doc = Jsoup.connect("http://www.educubeglobal.com/").get();
//通过Elements 对象获取da-slider下的内容
Elements elements1 = doc.select("[class=da-slider][id=da-slider]");
//获取所有<h2>标签的内容
Elements elements2 = elements1.select("h2");
//获取所有<img>标签的内容
Elements elements3 = elements1.select("img");
//获取所有<a>标签的内容
Elements elements4 = elements1.select("a");
for(int i=0;i<elements2.size();i++){
//将获取的内容全部放在 m 中
Map<String,String> m=new HashMap<>();
m.put("title",elements2.get(i).text());
m.put("img","http://www.educubeglobal.com"+elements3.get(i).attr("src"));
m.put("url",elements4.get(i).attr("href"));
map.add(m);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map ;
//return test();
}
来看一下MainActivity的代码:
package test.quxing.com.getnews;
import android.content.Intent;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
import com.jude.rollviewpager.OnItemClickListener;
import com.jude.rollviewpager.RollPagerView;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
private RollPagerView rollPagerView;
private ArrayList<String> imageUrlList ;
private ArrayList<String> linkUrlArray;
private ArrayList<String> titleList ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
ProgressAsyncTask asyncTask=new ProgressAsyncTask();
asyncTask.execute(10000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
rollPagerView = (RollPagerView) findViewById(R.id.view_rollpager);
}
public void getData(List<Map<String, String>> map) {
imageUrlList = new ArrayList<>();
linkUrlArray= new ArrayList<>();
titleList = new ArrayList<>();
for (int i=0;i<map.size();i++){
imageUrlList.add(map.get(i).get("img"));
linkUrlArray.add(map.get(i).get("url"));
titleList.add(map.get(i).get("title"));
}
rollPagerView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(int position) {
String url = linkUrlArray.get(position);
if(url==null){
Toast.makeText(MainActivity.this, "暂无该链接",
Toast.LENGTH_SHORT).show();
}
else {
Bundle bundle = new Bundle();
bundle.putString("url", url);
Intent intent = new Intent(MainActivity.this, BaseWebActivity.class);
intent.putExtras(bundle);
startActivity(intent);
}
}
});
rollPagerView.setAdapter(new RollViewAdapter(MainActivity.this,rollPagerView,imageUrlList,titleList));
// initBanner(imageUrlList,linkUrlArray,titleList);
}
class ProgressAsyncTask extends AsyncTask<Integer, Integer, List<Map<String,String>>> {
private List<Map<String,String>> map;
public ProgressAsyncTask() {
super();
map=new ArrayList<>();
}
@Override
protected List<Map<String,String>> doInBackground(Integer... params) {
Document doc = null;
try {
doc = Jsoup.connect("http://www.educubeglobal.com/").get();
Elements elements1 = doc.select("[class=da-slider][id=da-slider]");
Elements elements2 = elements1.select("h2");
Elements elements3 = elements1.select("img");
Elements elements4 = elements1.select("a");
for(int i=0;i<elements2.size();i++){
Map<String,String> m=new HashMap<>();
m.put("title",elements2.get(i).text());
m.put("img","http://www.educubeglobal.com"+elements3.get(i).attr("src"));
m.put("url",elements4.get(i).attr("href"));
map.add(m);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map ;
//return test();
}
@Override
protected void onPostExecute( List<Map<String,String>> result) {
getData(result);
}
// 该方法运行在UI线程当中,并且运行在UI线程当中 可以对UI空间进行设置
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Integer... values) {
}
}
}
上面代码先在onCreate中执行 声明并执行ProgressAsyncTask , 获取到网页内容后执行getData并对rollPagerView进行适配。下面来介绍rollPagerView的使用
rollPagerView
准备
导入rollPagerView的jar包,并添加依赖:
compile 'com.jude:rollviewpager:1.4.6'
详解
先来看下布局:
<com.jude.rollviewpager.RollPagerView
android:layout_width="match_parent"
android:layout_height="180dp"
android:background="@drawable/bg_user_card"
android:layout_margin="0dp"
android:orientation="vertical"
android:id="@+id/view_rollpager"
app:rollviewpager_play_delay="3000" >
</com.jude.rollviewpager.RollPagerView>
我们再来看下rollPagerView的适配器代码:
package test.quxing.com.getnews;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.jude.rollviewpager.RollPagerView;
import com.jude.rollviewpager.adapter.LoopPagerAdapter;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import java.util.ArrayList;
import java.util.List;
public class RollViewAdapter extends LoopPagerAdapter {
private List<String> imageIdList;//图片链接
private List<String> titleList;//标题
private DisplayImageOptions options;
private Context context;
private ImageLoader imageLoader;
public RollViewAdapter(Context context, RollPagerView viewPager, ArrayList<String> imageUrlList, ArrayList<String> titleList) {
super(viewPager);
this.context = context;
this.imageIdList = imageUrlList;
this.titleList = titleList;
// 初始化imageLoader 否则会报错
imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_launcher) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_launcher) // 设置图片加载或解码过程中发生错误显示的图片
.cacheInMemory(true) // 设置下载的图片是否缓存在内存中
.cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
.build();
}
@Override
public View getView(ViewGroup container, int position) {
View view = LayoutInflater.from(context).inflate(R.layout.item_viewpage, null);
ImageView imageView = (ImageView)view.findViewById(R.id.image);
TextView page = (TextView)view.findViewById(R.id.page);
TextView title = (TextView)view.findViewById(R.id.title);
imageLoader.displayImage(
(String) this.imageIdList.get(position),
imageView, options);
page.setText(position+1+"/"+imageIdList.size());
title.setText(titleList.get(position));
return view;
}
@Override
public int getRealCount() {
return imageIdList.size();
}
}
是不是和普通的listview适配器很相似,这里就不再多说了。我们再来看下上面代码中的ImageLoader和DisplayImageOptions,这就是我们接下来要介绍的universal-image-loader图片加载框架。
universal-image-loader图片加载框架
相信大家平时做Android应用的时候,多少会接触到异步加载图片,或者加载大量图片的问题,而加载图片我们常常会遇到许多的问题,比如说图片的错乱,OOM等问题,对于新手来说,这些问题解决起来会比较吃力,所以就有很多的开源图片加载框架应运而生,比较著名的就是Universal-Image-Loader。本文只介绍Universal-Image-Loader的简单使用,笔者觉得这篇介绍得很不错,感兴趣的朋友可以去了解看看。
准备
导入Universal-Image-Loader的jar包
详解
首先创建ImageLoader对象并对其初始化:
imageLoader = ImageLoader.getInstance();
ImageLoaderConfiguration是图片加载器ImageLoader的配置参数,这里是直接使用了createDefault()方法创建一个默认的ImageLoaderConfiguration。然后调用ImageLoader的init()方法将ImageLoaderConfiguration参数传递进去
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
我们使用DisplayImageOptions来配置显示图片的一些选项,这里添加了将图片缓存到内存中已经缓存图片到文件系统中,这样我们就不用担心每次都从网络中去加载图片了,设置如下(代码已给出注释):
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_launcher) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_launcher) // 设置图片加载或解码过程中发生错误显示的图片
.cacheInMemory(true) // 设置下载的图片是否缓存在内存中
.cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
.build();
好了,完成以上设置后就可以开始加载图片了,加载代码如下:
imageLoader.displayImage((String) this.imageIdList.get(position),imageView, options);
- (String) this.imageIdList.get(position)为我们要加载的图片链接
- imageView为我们要显示的控件的实例
- options即为我们刚刚配置显示图片的一些选项
-
好了,ImageLoader就简单介绍到这边。接下来我们在回到MainActivity,我们为rollPagerView设置的点击事件中:
String url = linkUrlArray.get(position); if(url==null){ Toast.makeText(MainActivity.this, "暂无该链接",Toast.LENGTH_SHORT).show(); } else { Bundle bundle = new Bundle(); bundle.putString("url", url); Intent intent = new Intent(MainActivity.this, BaseWebActivity.class); intent.putExtras(bundle); startActivity(intent); }
其中的BaseWebActivity就是接下来要介绍的WebView。
WebView
详解
来看一下布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <WebView android:id="@+id/wv_internet" android:layout_width="fill_parent" android:layout_height="fill_parent" android:fadeScrollbars="true" android:scrollbarStyle="insideOverlay" /> </LinearLayout>
接下来看下对于的BaseWebActivity(代码已经给出详细注释):
package test.quxing.com.getnews; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; /** * @Description:WebView界面,带自定义进度条显示 * @author http://blog.youkuaiyun.com/finddreams */ public class BaseWebActivity extends AppCompatActivity { private WebView webview; private ProgressDialog pd; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_baseweb); pd=new ProgressDialog(this); pd.setMessage("正在加载..."); Intent intent = getIntent(); Bundle bundle = intent.getExtras(); String url = bundle.getString("url"); go(url); //webview的简单设置 } public void go(String url){ webview=(WebView) findViewById(R.id.wv_internet); webview.loadUrl(url);//加载网页 WebSettings websettings=webview.getSettings(); websettings.setUseWideViewPort(true);//将图片调整到适合webview的大小 websettings.setLoadWithOverviewMode(true);// 缩放至屏幕的大小 websettings.setSupportZoom(true);//支持缩放 websettings.setBuiltInZoomControls(true);//设置支持缩放 webview.setWebViewClient(new WebViewClient(){ /** * //这个事件就是开始载入页面调用的,通常我们可以在这设定一个loading的页面,告诉用户程序在等待网络响应。 * */ @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { pd.show(); } /** * //在页面加载结束时调用。同样道理,我们知道一个页面载入完成,于是我们可以关闭loading 条,切换程序动作。 */ @Override public void onPageFinished(WebView view, String url) { pd.dismiss(); } }); } //后退键 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode== KeyEvent.KEYCODE_BACK&&webview.canGoBack()){ webview.goBack(); return true; } return super.onKeyDown(keyCode, event); } //菜单键 @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, 0, 0, "刷新"); menu.add(0, 0, 1, "后退"); menu.add(0, 0, 2, "前进"); return super.onCreateOptionsMenu(menu); } //菜单点击事件 @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getOrder()) { case 0: webview.reload(); break; case 1: if(webview.canGoBack()){ webview.goBack(); } break; case 2: if(webview.canGoForward()){ webview.goForward(); } break; } return super.onOptionsItemSelected(item); } }
- WebSettings是用于设置WebView的页面状态
- WebViewClient 回调对应的方法改变网页内容的呈现方式
- onKeyDown的作用是按返回键时, 不退出程序而是返回上一浏览页面
- WebView 加载界面主要调用三个方法:LoadUrl、LoadData、LoadDataWithBaseURL.(这里使用的是LoadUrl)
更多关于WebView的使用可以参考这篇博客 -