使用jsoup加载网页数据(一)

时间:2022-10-31 07:36:13

真的好久没更新博客了,最近做一个csdn的客户端用到了jsoup技术用于获取网页的数据和图片,很好用。只需要下载一个jsoup.jar的包然后布置到自己的项目的环境就可以用了。废话不多说,直接上图片

使用jsoup加载网页数据(一)使用jsoup加载网页数据(一)

这是通过jsoup直接获取到的数据然后展示出来。简述一下用到的技术主要有Jsoup解析html,异步加载任务,ImageLoader加载图片。

我们在浏览网页的时候都可以按F12查看网页代码,然后可以查看里面的各种元素。

使用jsoup加载网页数据(一)

可以看到每个新闻都是一个unit,每个unit里面有各种结点,我们只要去获得各种结点就能得到这里面的数据了(这里我讲一下我的技巧就是,遇到class,就是使用getElementsByClass,遇到一些标签比如<h1><h4>这种的,就使用getElementsByTag来获得结点,然后在这些<h1>下面的子标签的话就是使用child(i)来确定是第几个子标签),每个结点里包含了各种文字和图片链接,我们只要拿到这些再加载到我们的代码里就可以了。

先贴上最重要的jsoup解析html的代码

public class HttpUtil {

/**
* 根据传入的网址获取该网页的html
*
* @param urlStr
* @return
*/
public static String getHtml(String urlStr) {
StringBuffer sb = new StringBuffer();
URL url = null;
try {
url = new URL(urlStr);

HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setDoInput(true);
connection.setDoOutput(true);
if (connection.getResponseCode() == 200) {
// 得到输入流
InputStream input = connection.getInputStream();
byte[] b = new byte[1024];
int len;
while ((len = input.read(b)) != -1) {
sb.append(new String(b, 0, len, "UTF-8"));

}

}

} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return sb.toString();

}

/**
* 使用jsoup技术获取网页数据
*
* @param htmlStr
* @return
*/
public static List<News> getNews(String htmlStr) {

List<News> newses = new ArrayList<News>();
News news = null;

Document doc = Jsoup.parse(htmlStr);
Elements units = doc.getElementsByClass("unit");

for (int i = 0; i < units.size(); i++) {
news = new News();
// 获得一个element
Element unit = units.get(i);

// 得到标题
Element h1_ele = unit.getElementsByTag("h1").get(0);
Element h1_a_ele = h1_ele.child(0);
String title = h1_a_ele.text();
news.setTitle(title);

// 得到时间
Element h4_ele = unit.getElementsByTag("h4").get(0);
Element ago_ele = h4_ele.getElementsByClass("ago").get(0);
String date = ago_ele.text();
news.setDate(date);

// 得到dl这个结点
Element dl_ele = unit.getElementsByTag("dl").get(0);
// 得到图片
Element dt_ele = dl_ele.child(0);
Element img_ele = dt_ele.child(0);
String imageLink = img_ele.child(0).attr("src");
news.setImageLink(imageLink);

// 得到内容
Element dd_ele = dl_ele.child(1);
String content = dd_ele.text();
news.setContent(content);
newses.add(news);

}

return newses;

}

}
先传入网页的url然后获得该网页的html源码,再开始使用jsoup解析,可以边看网页边解析对着看更好理解,大致用法我上面讲过了。

News是一个实体类

/**
* 实体类
*
* @author sdf
*
*/
public class News {
private String id;
// 标题
private String title;
// 图片链接
private String imageLink;
// 内容
private String content;
private String date;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getImageLink() {
return imageLink;
}

public void setImageLink(String imageLink) {
this.imageLink = imageLink;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}

public String getDate() {
return date;
}

public void setDate(String date) {
this.date = date;
}

@Override
public String toString() {
return "News [id=" + id + ", title=" + title + ", imageLink="
+ imageLink + ", content=" + content + ", date=" + date + "]";
}

}
然后就是适配器的代码了,这个适配器的布局是各有各的想法了,你想怎么写就怎么写,当然写出好看优美的界面最好了

/**
* 适配器
*
* @author sdf
*
*/
public class NewsAdapter extends BaseAdapter {
private List<News> mDatas = new ArrayList<News>();
private LayoutInflater mInflater;
private DisplayImageOptions options;

public NewsAdapter(Context context, List<News> data) {

mInflater = LayoutInflater.from(context);
this.mDatas = data;
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.images)
.showImageForEmptyUri(R.drawable.images)
.showImageOnFail(R.drawable.images).cacheInMemory(true)
.cacheOnDisk(true).build();
}

public void addAll(List<News> news) {
this.mDatas.addAll(news);
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return mDatas.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return mDatas.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_news, null);
viewHolder = new ViewHolder();
viewHolder.title = (TextView) convertView.findViewById(R.id.title);
viewHolder.content = (TextView) convertView
.findViewById(R.id.content);
viewHolder.date = (TextView) convertView.findViewById(R.id.date);
viewHolder.image = (ImageView) convertView
.findViewById(R.id.images);
convertView.setTag(viewHolder);

} else {

viewHolder = (ViewHolder) convertView.getTag();

}
News news = mDatas.get(position);
viewHolder.title.setText(news.getTitle());
viewHolder.content.setText(news.getContent());
viewHolder.date.setText("发表于 " + news.getDate());
// 使用imagelaoder加载图片
if (news.getImageLink() != null) {
viewHolder.image.setVisibility(View.VISIBLE);
ImageLoader.getInstance().displayImage(news.getImageLink(),
viewHolder.image, options);

} else {
viewHolder.image.setVisibility(View.GONE);

}
return convertView;
}

class ViewHolder {

TextView title;
TextView content;
TextView date;
ImageView image;

}
}
这里用到了ImageLoader这个开源项目,不懂的先去自行百度,非常好用。

item_news.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp" >

<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="整合测试APM,Testin推出O2O一站式测试服务"
android:textSize="18sp"
android:textColor="#000000"
android:textStyle="bold" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<ImageView
android:id="@+id/images"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/images"
android:visibility="visible" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="top" >

<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:text="8月25日,Testin举行“O2O一站式测试服务”新闻发布会,正式推出集功能测试、兼容性测试、APM等为一体的O2O一站式测试服务。Testin云测总裁徐琨出席会议,并围绕“为O2O而生的一站式测试服务”发表主题演讲。"
android:textColor="#3D3D3D" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="bottom" >

<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|right"
android:paddingTop="8dp"
android:text="发表于2015-08-28 14:28" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

</LinearLayout>

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sdf.android_jsoup.MainActivity" >

<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="visible" />

</RelativeLayout>

了解ImageLoader就知道它是单一实例的,所以必须要在application里面实例。

public class MyApplication extends Application {
@Override
public void onCreate() {
// TODO Auto-generated method stub
// imageloader创建单一实例
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
getApplicationContext())
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.diskCacheSize(50 * 1024 * 1024)
.tasksProcessingOrder(QueueProcessingType.LIFO).build();
ImageLoader.getInstance().init(config);

ImageLoader.getInstance().init(config);
}
}


注意,必须要到AndroidManifest.xml里面注册这个application, <application
        android:name="com.sdf.android_jsoup.MyApplication".../>

最后就是MainActivity.class

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.ProgressBar;

import com.sdf.android_jsoup.adapter.NewsAdapter;
import com.sdf.android_jsoup.bean.News;
import com.sdf.android_jsoup.util.HttpUtil;

public class MainActivity extends Activity {
private ListView listView;
private NewsAdapter mAdapter;
private ProgressBar progressBar;
private List<News> mDatas;
// 网页的地址
public static final String NEWS_URL_YIDONG = "http://mobile.csdn.net/";

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

listView = (ListView) findViewById(R.id.listView);
progressBar = (ProgressBar) findViewById(R.id.progressbar);
mDatas = new ArrayList<News>();

mAdapter = new NewsAdapter(getApplicationContext(), mDatas);
new getDataTask().execute();
listView.setAdapter(mAdapter);

}

/**
* 异步加载数据类
*
*/
class getDataTask extends AsyncTask<Void, Void, List<News>> {

@Override
protected List<News> doInBackground(Void... params) {
// TODO Auto-generated method stub
String html = HttpUtil.getHtml(NEWS_URL_YIDONG);
// 获得数据
mDatas = HttpUtil.getNews(html);
// 返回数据
return mDatas;
}

@Override
protected void onPostExecute(List<News> result) {
// TODO Auto-generated method stub
// 增加数据到适配器里
mAdapter.addAll(result);
mAdapter.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
}
}

}

这里因为是涉及到网络加载数据,所以必须要异步加载,我是用了AsyncTask这个类来加载的,你也可以选择使用thread来加载。

以上就是这次的内容了,需要源码的可以留言。

别忘了在AndroidManifext.xml里添加网络权限和读写权限。