Android学习笔记:Jsoup解析、截取HTML

时间:2022-11-01 09:22:12

作业内容是 截取学校教学平台网站的新闻列表,然后在Android界面中用ListView显示出来,点击ListView中的Button可以弹出详细内容的新Activity。

本次学习重点如下:

1.截取HTML代码

2.用Jsoup解析HTML代码


详细要求:

1.BNUZH网络教学综合平台  打开之后可以看到通知公告。

Android学习笔记:Jsoup解析、截取HTML

2.查看源代码,我们可以发现是这段的内容

Android学习笔记:Jsoup解析、截取HTML

本次实验目的就是要抓取这里的代码

每一条<li>的内容都要转化并且在Android中显示出来


3.效果图1

Android学习笔记:Jsoup解析、截取HTML

为了方便显示 上面是一个TextView用来测试 截取的代码

下面的ListView是用于显示后来的经过转化的元素

这样看来,很快就能做到片总NGA客户端那种论坛抓取的形式啦。



实现过程以及重点:

1.用Android获取HTML源代码(UTF-8 不然默认是GB2312中文会乱码)

这部分网络连接需要用到异步线程 更新UI记得在onPostExecuted中完成

 /* 连接EOL的方法 返回整个网页经过截取之后的的源代码 */
public String ConnectEOL() {
String result = "";
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(URL_EOL);
HttpResponse response = httpclient.execute(httppost);
String Res = EntityUtils.toString(response.getEntity(), "UTF-8");
int st = Res.indexOf("<div class=\"notifywrap\">");
int ed = Res.indexOf("<div class=\"notify-more\">");
String content = Res.substring(st, ed);
st = content.indexOf("<ul>") + 4;
ed = content.indexOf("</ul>");
content = content.substring(st, ed);
result = content;
} catch (Exception e) {
Log.d(TAG, e.toString());
}
return result;
}

这里先获得整个HTML页面的代码 用String保存

然后对这个字符串进行一步步的截取 使得只剩下ul标签里面的多个li标签。

2.用Jsoup解析HTML代码

获取了

Android学习笔记:Jsoup解析、截取HTML

这串代码之后,如何获取li标签里面的span标签里面的通知时间呢?

如何获取li里面的a标签的href值 和title值呢?~请用Jsoup解析HTML 转化成的String字符串。

Jsoup需要下载 百度Jsoup 下载1.7.3jar包导入。

地址 Jsoup 下载地址

导入Jsoup.jar包请注意,你以为在BuildPath中Add ExJar就行了?Android4.0之后更新了导入额外包的方式 需要你手动将jar包复制到工程目录下的libs文件夹。然后再从BuildPath中选择倒入,才不会报错。


下面是Jsoup解析上面这段代码

/* 对源代码进行解析截取的方法 返回一个News数组 */
public List<News> getNews(String HTMLCode) {
List<News> newsList = new ArrayList<News>();
Document doc = Jsoup.parse(HTMLCode);
Log.d(TAG, "解析html中");
Elements lis = doc.getElementsByTag("li");
Log.d(TAG, "lis的size " + lis.size());
for (Element li : lis) {
String newstime = li.getElementsByTag("span").text();
String newstitle = li.getElementsByTag("a").text();
String newsurl = li.getElementsByTag("a").attr("href");
newsurl=newsurl.replace("../../", "http://eol.bnuz.edu.cn/eol/");
Log.d(TAG, newstime);
Log.d(TAG, newstitle);
Log.d(TAG, newsurl);

News newst=new News();
newst.setNewsTime(newstime);
newst.setNewsTitle(newstitle);
newst.setNewsUrl(newsurl);
newsList.add(newst);
}
return newsList;
}

先用一个Elements 元素组来储存所有的<li></li>标签中间的内容。

然后遍历这个Elements组 我们把<li></li>里面诸如<span></span>   <a></a>中的span 和a 叫做Tag ,也就是标签。 用getElementsByTag(标签名)来取值 返回一个Elements类型。如果需要得到的是<span>Aquariuslt</span> 中Aquariuslt的值,则需要用这个Elements.text()方法取值。

如果要获取<a href="www.baidu.com"></a> 则需要用Elements.attr("href")方法来获得这个www.baidu.com 字符串。


在这里,我发现a标签里面的href值都是相对路径,所以我机智的用replace更改了URL使得是绝对路径。

下面是源代码:

Activity_news_list.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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".NewsList" >

<TextView
android:id="@+id/TV_HTMLCode"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_above="@+id/LV_Result"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:scrollbars="vertical" />

<ListView
android:id="@+id/LV_Result"
android:layout_width="match_parent"
android:layout_height="230dp"
android:layout_alignLeft="@+id/TV_HTMLCode"
android:layout_alignParentBottom="true" >
</ListView>

</RelativeLayout>


NewsList.java

package bnuz.alt.eol_newscatcher;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import bnuz.alt.news.News;

import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

@SuppressWarnings("unused")
public class NewsList extends Activity {
private TextView TV_HTMLCode;
private String URL_EOL = "http://eol.bnuz.edu.cn/eol/homepage/common/",
TAG = "ATAG";
private List<News> NewsList;
private ListView LV_Result;
private ArrayAdapter<String> LV_Adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news_list);
LV_Result = (ListView) findViewById(R.id.LV_Result);
TV_HTMLCode = (TextView) findViewById(R.id.TV_HTMLCode);
TV_HTMLCode.setMovementMethod(ScrollingMovementMethod.getInstance());
ConnectTask C1 = new ConnectTask();
C1.execute();

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.news_list, menu);
return true;
}

public class ConnectTask extends AsyncTask<Void, Void, String> {

@Override
protected String doInBackground(Void... params) {
String result = ConnectEOL();
return result;
}

@Override
protected void onPostExecute(String result) {
// TV_HTMLCode.setText(result);
NewsList = getNews(result);
List<String> NewsTitles = new ArrayList<String>();
for (News news : NewsList) {
TV_HTMLCode.append(news.getNewsTitle() + "\n");
TV_HTMLCode.append(news.getNewsTime() + "\n");
TV_HTMLCode.append(news.getNewsUrl() + "\n");
NewsTitles.add(news.getNewsTitle());
}
/* 为ListView添加适配器 */

LV_Adapter = new ArrayAdapter<String>(NewsList.this,
android.R.layout.simple_list_item_1, NewsTitles);
LV_Result.setAdapter(LV_Adapter);

/* 为ListView添加点击打开对应网页功能 */
LV_Result.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
final Uri uri = Uri.parse(NewsList.get(arg2).getNewsUrl());
final Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
}

});
super.onPostExecute(result);

}

}

/* 连接EOL的方法 返回整个网页经过截取之后的的源代码 */
public String ConnectEOL() {
String result = "";
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(URL_EOL);
HttpResponse response = httpclient.execute(httppost);
String Res = EntityUtils.toString(response.getEntity(), "UTF-8");
int st = Res.indexOf("<div class=\"notifywrap\">");
int ed = Res.indexOf("<div class=\"notify-more\">");
String content = Res.substring(st, ed);
st = content.indexOf("<ul>") + 4;
ed = content.indexOf("</ul>");
content = content.substring(st, ed);
result = content;
} catch (Exception e) {
Log.d(TAG, e.toString());
}
return result;
}

/* 对源代码进行解析截取的方法 返回一个News数组 */
public List<News> getNews(String HTMLCode) {
List<News> newsList = new ArrayList<News>();
Document doc = Jsoup.parse(HTMLCode);
Log.d(TAG, "解析html中");
Elements lis = doc.getElementsByTag("li");
Log.d(TAG, "lis的size " + lis.size());
for (Element li : lis) {
String newstime = li.getElementsByTag("span").text();
String newstitle = li.getElementsByTag("a").text();
String newsurl = li.getElementsByTag("a").attr("href");
newsurl = newsurl.replace("../../", "http://eol.bnuz.edu.cn/eol/");
Log.d(TAG, newstime);
Log.d(TAG, newstitle);
Log.d(TAG, newsurl);

News newst = new News();
newst.setNewsTime(newstime);
newst.setNewsTitle(newstitle);
newst.setNewsUrl(newsurl);
newsList.add(newst);
}
return newsList;
}
}


News类 

package bnuz.alt.news;

public class News {
private String newsTime;
private String newsUrl;
private String newsTitle;

public News() {

}

public News(String newsTitle, String newsTime, String newsUrl) {
this.newsTime = newsTime;
this.newsUrl = newsUrl;
this.newsTitle = newsTitle;
}

public String getNewsTime() {
return newsTime;
}

public void setNewsTime(String newsTime) {
this.newsTime = newsTime;
}

public String getNewsUrl() {
return newsUrl;
}

public void setNewsUrl(String newsUrl) {
this.newsUrl = newsUrl;
}

public String getNewsTitle() {
return newsTitle;
}

public void setNewsTitle(String newsTitle) {
this.newsTitle = newsTitle;
}

}