ImageLoad+RollViewPage+Jsoup+WebView带你轻松实现抓取网页数据(附源码)

来源:互联网 发布:阮一峰博客 js面向对象 编辑:程序博客网 时间:2024/05/22 13:19

在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.csdn.net/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的使用可以参考这篇博客

  • 好啦,源码地址:https://github.com/HeyGoing/GetNews

    原创粉丝点击