您的位置:首页 > Web前端 > JavaScript

用Jsoup解析静态网页数据

2015-07-19 11:08 561 查看
在个人开发中,很多人都会遇到这样的问题:我有了一个好想法,但是却没有数据源,有时找到了数据,但是那是人家的数据,你没有接口.

这时候你会不会像看着肉却不能吃的那种干着急呢.现在告诉你一个好工具Jsoup,它能够帮我们把人家的网页数据窃取出来,不过Jsoup

有个缺陷,就是只能解析静态的网页数据,对于动态的数据,那是无能为力.还有窃取数据是有被告的风险的,所以呢,不要把人家未授权

的数据用作商业用途.还有就是这是解析的数据,万一某天人家的网页结构更改了,你也就无法再获取数据了,这时候你的程序就有可能出现崩溃哦。当然你也可以根据新的网页结构重新编写解析代码,再次获取数据。

1.首先要学会Html的Dom结构

关于Html的Dom的讲解,在W3school上有比较全面的讲解,常用方法有:

Document.getElementById(String id)返回带有指定ID的元素

Document.getElementsByClass(String className) :返回包含带有指定类名的所有元素的节点列表.

Document.getElementsByTagName(String tag) :返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)

对于Elements,我们可以通过select(String tag)获取Elements下的子节点集合Elements.

Elements可以通过get(int index)获取集合的特定节点,获取到特定节点后我们可以调用节点的text()方法,就可以获取节点包含的文字内容.

如果要获取节点的内部属性:比如说href,bgcolor等.我们可以使用节点的attr(String属性)来取得。

还有一些节点的方法比如说:child(int index)获取特定节点的特定子节点

children():特定节点的获取所有子节点

2.分析网页的Html结构

找到你要的网页数据,鼠标右键查看元素,这时候就会弹出Html的代码。这时候我们就可以分析观察它的结构了。最重要的是把获取的 Document的文本打印到 控制台,看看数据是否在里面,要不然就是白忙活了.毕竟有些是动态的数据。



我们可以看到一个<tbody></tbody>包含了很多个<tr节点,这些内容就在<td节点的子节点<a里面。 我们可以看到<tr的节点的class属性都是一样的,我们可以很轻易地获取所有的<tr节点;接下来呢就要获取内容所在的<td节点了.这里只有第1和第2个节点有内容(下标是从0开始的),所以只获取它们就好了;接着取出<a节点的文本内容和href属性,因为我们要获取新闻条对应的内容.

3.最后就是解析你的数据了.

首先获取Jsoup的jar包,这个网上可以下载.

获取Document对象,有两种方法。

1.Jsoup.connect(String url).timeout(int millis).get();

2.你可以通过HttpGet(String url)取得Html的实体.然后通过Jsoup.parse(String html)获得对应的Document对象

获取玩了就回到开始的解析数据的方法,然后就是得到你想要的数据了。

下面是我解析的例子,你们也可以参考张鸿洋大牛的博客,至于动态的网页解析你们自己去探索吧。

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.util.Log;

import com.shite.jobsmile_adapter.NewsAdapter;
import com.shite.jobsmile_db.CampusNewsBase;
import com.shite.jobsmile_modle.News;

/**
* 解析学校网页新闻的异步类
*
* @author HuberJobs
*
*/
public class NewsAsyncTask extends AsyncTask<Void, Void, List<News>> {

private NewsAdapter adapter;
private String table;

private CampusNewsBase campusNewsBase;
private SQLiteDatabase newsWriter;

public NewsAsyncTask(NewsAdapter adapter, CampusNewsBase campusNewsBase, String table) {
this.adapter = adapter;
this.table =table;
this.campusNewsBase = campusNewsBase;
}

public NewsAsyncTask(NewsAdapter adapter) {
this.adapter = adapter;
}

//获取新闻的同时更新数据库
@Override
protected List<News> doInBackground(Void... params) {

String URL = "http://xc.hfut.edu.cn/120/list.htm";
List<News> newsList = new ArrayList<News>();
Document doc;
newsWriter = campusNewsBase.getWritableDatabase();
newsWriter.delete(table, null, null);

try {
doc = Jsoup.connect(URL).timeout(3000).get();
// 拿到<tr>节点集,每个<tr>节点包含了一条新闻标题和日期
Elements elements = doc.getElementsByClass("articlelist2_tr");
for (Element links : elements) {
// 取得每条新闻的标题日期和资源地址
String news_title = links.select("td").get(1).text();
String news_date = links.select("td").get(2).text();
String news_href = links.select("td").get(1).child(0).attr("href");

//新闻写入数据库
ContentValues newsValues = new ContentValues();
newsValues.put("news_title", news_title);
newsValues.put("news_date", news_date);
newsValues.put("news_href", news_href);
newsWriter.insert(table, null, newsValues);

//新闻对象
News news = new News();
news.setTitle(news_title);
news.setTime(news_date);
news.setUrl(news_href);

newsList.add(news);

}
Log.i("ListData", newsList.size() + ".....");
} catch (IOException e) {
e.printStackTrace();
}finally{

newsWriter.close();
}
return newsList;
}

@Override
protected void onPostExecute(List<News> result) {
super.onPostExecute(result);
adapter.setNewsData(result);
adapter.notifyDataSetChanged();
System.out.println("网络操作。。。");
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: