Jsoup抓取网页数据完成一个简易的Android新闻APP
前言:作為一個籃球迷,每天必刷NBA新聞。用了那么多新聞APP,就想自己能不能也做個簡易的新聞APP。于是便使用Jsoup抓取了虎撲NBA新聞的數(shù)據(jù),完成了一個簡易的新聞APP。雖然沒什么技術(shù)含量,但還是寫一下過程,滿足一下菜鳥小小的成就感。
關(guān)于Jsoup
- jsoup 是一款 Java 的 HTML 解析器,可直接解析某個 URL 地址、HTML 文本內(nèi)容。它提供了一套非常省力的 API,可通過 DOM,CSS 以及類似于 jQuery 的操作方法來取出和操作數(shù)據(jù)。
- Jsoup的中文文檔:點擊這里
- Jsoup的jar包下載地址:點擊這里
分析與思路
虎撲NBA新聞網(wǎng)頁的新聞列表如圖所示:
我們所要做的便是獲取圖中每條新聞的新聞標題、新聞概要、新聞時間與來源以及新聞的鏈接地址這四個信息,而后用一個實體類News封裝上述四個數(shù)據(jù),再布局到ListView上。點擊ListView的每個子項,便將該子項所顯示的新聞的鏈接地址用一個WebView顯示出來,便大功告成。效果如圖:
具體實現(xiàn)過程
1.在AndroidStudio新建工程JsoupTest,而后將Jsoup的jar包【下載地址】拷到項目的libs下,然后右鍵Add As Library...
2.修改activity_main.xml的布局,簡單加入一個ListView,并設(shè)置一下Listview的每兩個子項間的間隔的距離和顏色
<?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"><ListViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/news_lv"android:dividerHeight="7dp"android:divider="#dcdcdc"></ListView> </LinearLayout>3.建立一個實體類News來封裝我們等會要從網(wǎng)頁中獲取的新聞的標題、概要、時間與來源、鏈接地址這四個數(shù)據(jù)。很簡單,用四個變量分別代表上述四個數(shù)據(jù),并建立相應(yīng)的構(gòu)造方法以及四個變量的get與set方法。
public class News {private String newsTitle; //新聞標題private String newsUrl; //新聞鏈接地址private String desc; //新聞概要private String newsTime; //新聞時間與來源public News(String newsTitle, String newsUrl, String desc, String newsTime) {this.newsTitle = newsTitle;this.newsUrl = newsUrl;this.desc = desc;this.newsTime = newsTime;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}public String getNewsTime() {return newsTime;}public void setNewsTime(String newsTime) {this.newsTime = newsTime;}public String getNewsTitle() {return newsTitle;}public void setNewsTitle(String newsTitle) {this.newsTitle = newsTitle;}public String getNewsUrl() {return newsUrl;}public void setNewsUrl(String newsUrl) {this.newsUrl = newsUrl;} }4.最重要的一步:利用Jsoup獲取虎撲NBA新聞網(wǎng)頁的數(shù)據(jù),并封裝到News實體類中。就簡單概述下實現(xiàn)方法
- 查看虎撲NBA新聞的網(wǎng)頁源代碼。谷歌瀏覽器,右鍵-查看網(wǎng)頁源代碼。其他瀏覽器應(yīng)該都差不多。
我們直接查看顯示新聞列表的這部分代碼,我們截圖下兩條新聞的代碼來進行分析- 新聞1源代碼:
- 新聞2源代碼:
- 新聞1源代碼:
-
分析上圖兩條新聞的源代碼,找到我們所打算要獲取的新聞的標題、概要、時間與來源、鏈接地址這四個數(shù)據(jù)。我們可以發(fā)現(xiàn)在每條新聞的[div class="list-hd"][/div]這個標簽下,存在新聞的鏈接地址與新聞的標題這兩個數(shù)據(jù)。而我們所要做的便是利用Jsoup將這兩個數(shù)據(jù)解析出來:
首先用Jsoup.connect(“所要抓取數(shù)據(jù)的網(wǎng)址”).get()獲取到一個Document對象
Document doc = Jsoup.connect("https://voice.hupu.com/nba/").get();用doc.select("div.list-hd")這個方法,返回一個Elements對象,封裝了每條新聞[div class="list-hd"][/div]標簽中的內(nèi)容,數(shù)據(jù)格式為:[{新聞1},{新聞2},{新聞3},{新聞4}......]
Elements titleLinks = doc.select("div.list-hd");for(Element e:titleLinks){ String title = e.select("a").text(); String uri = e.select("a").attr("href");}
用for循環(huán)遍歷titleLinks,對于每個Element對象:
用e.select("a").text()便獲取到[a][/a]間的內(nèi)容,即新聞標題;
用e.select("a").attr("href")便獲取到每個標簽中的href的值,即新聞的鏈接地址 - 同理對于另外兩個數(shù)據(jù):新聞簡介和新聞時間及來源,我們分析源代碼并進行解析
- 新聞簡介源代碼
用如下代碼獲得新聞簡介
Elements descLinks = doc.select("div.list-content"); for(Element e:titleLinks){ String desc = e.select("span").text(); }- 新聞時間及來源源代碼
用如下代碼獲得新聞時間與來源
Elements timeLinks = doc.select("div.otherInfo"); for(Element e:timeLinks){ String time = e.select("span.other-left").select("a").text(); }
- 新聞時間及來源源代碼
-
綜上,我們就獲取到了我們所需要的數(shù)據(jù)了,為此我們在MainActivity中聲明一個getNews()方法,在方法中,我們開啟一個線程來進行數(shù)據(jù)的獲取。完整代碼如下:
private void getNews(){new Thread(new Runnable() {@Overridepublic void run() {try{//獲取虎撲新聞20頁的數(shù)據(jù),網(wǎng)址格式為:https://voice.hupu.com/nba/第幾頁 for(int i = 1;i<=20;i++) {Document doc = Jsoup.connect("https://voice.hupu.com/nba/" + Integer.toString(i)).get();Elements titleLinks = doc.select("div.list-hd"); //解析來獲取每條新聞的標題與鏈接地址Elements descLinks = doc.select("div.list-content");//解析來獲取每條新聞的簡介Elements timeLinks = doc.select("div.otherInfo"); //解析來獲取每條新聞的時間與來源//for循環(huán)遍歷獲取到每條新聞的四個數(shù)據(jù)并封裝到News實體類中for(int j = 0;j < titleLinks.size();j++){String title = titleLinks.get(j).select("a").text();String uri = titleLinks.get(j).select("a").attr("href");String desc = descLinks.get(j).select("span").text();String time = timeLinks.get(j).select("span.other-left").select("a").text();News news = new News(title,uri,desc,time);newsList.add(news);}}Message msg = new Message();msg.what = 1;handler.sendMessage(msg);}catch (Exception e){e.printStackTrace();}}}).start(); }上一段代碼相信通過備注就可以理解了,通過解析虎撲NBA新聞20頁的每一頁的網(wǎng)址,獲取到每條新聞所需的數(shù)據(jù),封裝到實體類News中,再加入到MainActivity中聲明的泛型為News的List即newsList中。等全部20頁數(shù)據(jù)都獲取到之后,用Message.what=1來作為數(shù)據(jù)加載完成的標志,并用Handler.sendMessage()將子線程的消息發(fā)送到主線程,通知主線程數(shù)據(jù)已加載完成,可以將數(shù)據(jù)加載到ListView上顯示出來。
5.剩下的就簡單了 ,為ListView做相關(guān)的配置
- news_item.xml:為ListView的item指定布局。放置三個TextView用來顯示新聞標題,新聞概要,新聞時間及來源;
- NewsAdapter.java:為ListView加載數(shù)據(jù)
6.建立NewsDisplayActivity用于顯示新聞的具體內(nèi)容。
布局activity_display_news.xml:簡單放入一個WebView,用于顯示新聞
<?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"><WebViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/web_view"></WebView></LinearLayout>NewsDisplayActivity.java
public class NewsDisplayActvivity extends AppCompatActivity {private String newsUrl;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_news_display);newsUrl = getIntent().getStringExtra("news_url");WebView webView = (WebView) findViewById(R.id.web_view);webView.getSettings().setJavaScriptEnabled(true);webView.setWebViewClient(new WebViewClient());webView.loadUrl(newsUrl);} }7.MainActivity用getNews()獲取到數(shù)據(jù)后,在handlerMessage()方法里接受到子線程獲取完數(shù)據(jù)的消息后,開始為ListView加載數(shù)據(jù)。并為ListView的item設(shè)置點擊事件,當點擊item時,將該item所對應(yīng)的新聞的網(wǎng)址傳遞給NewsDisplayActivity,NewsDisplayActivity得到網(wǎng)址后用WebView加載該網(wǎng)址,便可看到新聞
public class MainActivity extends AppCompatActivity {private List<News> newsList;private NewsAdapter adapter;private Handler handler;private ListView lv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);newsList = new ArrayList<>();lv = (ListView) findViewById(R.id.news_lv);getNews();handler = new Handler(){@Overridepublic void handleMessage(Message msg) {if(msg.what == 1){adapter = new NewsAdapter(MainActivity.this,newsList);lv.setAdapter(adapter);lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {News news = newsList.get(position);Intent intent = new Intent(MainActivity.this,NewsDisplayActvivity.class);intent.putExtra("news_url",news.getNewsUrl());startActivity(intent);}});}}};}private void getNews(){new Thread(new Runnable() {@Overridepublic void run() {try{//獲取虎撲新聞20頁的數(shù)據(jù),網(wǎng)址格式為:https://voice.hupu.com/nba/第幾頁for(int i = 1;i<=20;i++) {Document doc = Jsoup.connect("https://voice.hupu.com/nba/" + Integer.toString(i)).get();Elements titleLinks = doc.select("div.list-hd"); //解析來獲取每條新聞的標題與鏈接地址Elements descLinks = doc.select("div.list-content");//解析來獲取每條新聞的簡介Elements timeLinks = doc.select("div.otherInfo"); //解析來獲取每條新聞的時間與來源for(int j = 0;j < titleLinks.size();j++){String title = titleLinks.get(j).select("a").text();String uri = titleLinks.get(j).select("a").attr("href");String desc = descLinks.get(j).select("span").text();String time = timeLinks.get(j).select("span.other-left").select("a").text();News news = new News(title,uri,desc,time);newsList.add(news);}}Message msg = new Message();msg.what = 1;handler.sendMessage(msg);}catch (Exception e){e.printStackTrace();}}}).start();}}最后記得在AndroidManifest中添加網(wǎng)絡(luò)請求的權(quán)限
2017.05.19更新(Github同步更新)
由于虎撲新聞網(wǎng)頁做了調(diào)整,去除了新聞簡介,所以這部分內(nèi)容就獲取不到了,所以相應(yīng)的要修改代碼,只需要getNews()方法中做三個修改
如下圖,獲取新聞簡介的兩句代碼注釋掉,News構(gòu)造對象時,新聞簡介參數(shù)傳入null。這樣改動較小,界面會丑點,自行調(diào)整便可。
源碼下載地址:請戳這里
總結(jié):雖然只是一個簡單的應(yīng)用,但還是有所收獲。有什么錯誤的地方,歡迎指出。菜鳥的點滴積累,希望能早日有所成長
轉(zhuǎn)自:http://www.cnblogs.com/AaronPasi/p/6344123.html
總結(jié)
以上是生活随笔為你收集整理的Jsoup抓取网页数据完成一个简易的Android新闻APP的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL数据库乱码 - Linux下乱
- 下一篇: struts2 s:if标签以及 #,%