Recent in Recipes

簡單使用JSoup抓取xml網站資料(含android範例)

  關於抓資料,第一個想法應該是python,不過因為學了java,想透過java抓取資料,於是開啟我查詢java爬資料的資料,除了查到ETL外,jsoup應該是最方便的"套件"了。
  jsoup說明白他就是java的library(jar),也就是人家寫好的套件然後造福我們這些寫程式的人用,這真的是很厲害的地方!我在網路上參考了
【JAVA】使用JSOUP讓JAVA取得網頁上的文字 (Example for download)這篇文章雖然寫得很簡單但是語法跟解說很清楚謝謝大大 =D,那我的廢話到這裡開始解說我的程式囉!

  jsoup方便的原因是因為不管是html,還是xml都是屬於標籤語言,而jsoup就是根據標籤抓取裡面的資訊,在打程式之前我們有些前置作業要做:
1.前往官方網站 http://jsoup.org/download 下載jar
2.開啟java專案匯入jar(這裡使用netbean)
12
其實netbean和eclipse匯入的方法差不多所以大家不用太擔心。
本篇文章是抓取政府opendata的資料放置本機伺服器,其資料格式為xml,
下載網址如下:
程式碼:CWBTSU.xml

<br data-mce-bogus="1">

CWB-TSU10300101-2014-0920-073000

CWB_SC@scman.cwb.gov.tw

2014-09-20T07:30:00+08:00

Actual

Issue

CWB

Public

海嘯資訊

zh-TW

2014-09-20T07:30:00+08:00

2014-09-20T15:30:00+08:00

海嘯警報

103001

第1報

頃獲太平洋海嘯警報中心通知,103年09月20日07時21分(臺灣時間),在震央東經137﹒41度、北緯9﹒19度,發生規模8﹒7地震。該中心研判可能引發海嘯,經初步推算,海嘯湧浪預計臺灣時間103年09月20日09時41分到達臺灣,請臺灣沿海地區提高警覺嚴加防範。

橙色

http://scweb.cwb.gov.tw/GraphicContent.aspx?ItemId=3&amp;fileString=10300101

2014-09-20T07:21:00+08:00

137.41

9.19

亞普海溝

10.0

8.7

美國太平洋海嘯警報中心

東南沿海地區

臺東縣成功鎮至屏東縣滿州鄉沿岸

1至3公尺

2014-09-20T09:41:00+08:00

橙色

predict

東部沿海地區

宜蘭縣南澳鄉至臺東縣長濱鄉沿岸

1至3公尺

2014-09-20T09:51:00+08:00

橙色

predict

東北沿海地區

宜蘭縣頭城鎮至蘇澳鎮沿岸

1至3公尺

2014-09-20T09:51:00+08:00

橙色

predict

西南沿海地區

臺南市至屏東縣恆春鎮沿岸

1至3公尺

2014-09-20T10:01:00+08:00

橙色

predict

北部沿海地區

新北市及基隆市沿岸

1至3公尺

2014-09-20T10:11:00+08:00

橙色

predict

海峽沿海地區

桃園縣至嘉義縣沿岸,以及澎湖縣、金門縣與連江縣等離島區域

小於1公尺

2014-09-20T10:51:00+08:00

黃色

predict



其實這裡都已經定義好資料了,每個標籤都有他們所呈現的資訊,所以在抓取資料時會相對的單純很多!
接下來直接來看程式碼

<Java程式端>
public static void main(String[] args) throws Exception {

URL url = new URL("server位置+檔名,以本機為例EX:http://127.0.0.1/ CWBTSU.xml ");

Document xmlc =  Jsoup.parse(url, 3000); //使用Jsoup解析網頁

try {

Elements datas = xmlc.select("warningArea"); //解析的元素為warningArea的標籤

for(Element data : datas){

System.out.println(data.text());

}

//使用for each取出資料並顯示

System.out.println("Is "+datas.get(0).text());

//這裡是取出warningArea標籤的第一個內容,即get(0),如果要取第二個內容為get(1)

} catch (Exception e) {

}
}


其執行結果為
3
表示我們已經把warningArea標籤內容取出了,大家可以參考一下。
如果程順利的顯示結果就表示完成了!那如果要搭配android的話如果java程式框架已經出來了,不過要使用執行緒來執行,因為有牽涉網路存取,可能會導致程式timeout,接下來附上程式碼。
首先是畫面的layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
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="com.example.jsouptest.MainActivity">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World!"
android:id="@+id/hi"
android:layout_above="@+id/button"
android:textAllCaps="false"
android:textAlignment="center" />

<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:id="@+id/button" />
</RelativeLayout>
再來是權限檔我們需要網路存取權限
 ※<uses-permission android:name="android.permission.INTERNET" /></pre>
所以所有程式碼如下
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.jsouptest">
<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
最後就是java檔了
 

 import android.app.Activity;
 import android.support.v7.app.AppCompatActivity;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 import android.widget.TextView;

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

 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;

public class MainActivity extends Activity {
  TextView hi;
  URL url;
  Thread go;
  StringBuilder tmp = new StringBuilder();
  int i = 1;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     Button button = (Button) findViewById(R.id.button);
     hi = (TextView) findViewById(R.id.hi);

     button.setOnClickListener(new Button.OnClickListener() {
       @Override
       public void onClick(View v) {
         go = new Thread(readData);
         go.start();
       }
     });

 }

 private Runnable readData = new Runnable() {
   public void run() {
   try {
   //(要解析的文件,timeout)

      url = new URL("在這裡輸入server位置與檔案(這裡檔案名為上面的xml) ");

      Document xmlDoc =&nbsp; Jsoup.<em>parse</em>(url,3000);
      Elements title = xmlDoc.select("warningArea"); <em>//要解析的tag元素為warningArea這標籤</em>

      //Elements tables = xmlDoc.select("center&gt;table");
      tmp.delete(0,tmp.length());
      for(int i =0; i&lt;title.size() ; i++){
        Log.<em>e</em>("Kevin Test",title.text());
        tmp.append(i+1+title.get(i).text()+"&nbsp;&nbsp;&nbsp; "+"\n\n");

      }
    hi.setText(tmp);
    //System.out.println("Is "+title.get(0).text());
    } catch (Exception e) {
  }
 }
 };
 }



其顯示結果如下:
messageImage_1485014148608.jpg
這是一開始的畫面
messageImage_1485014154111.jpg
當按下按鈕時,會把xml中所有標籤資訊解譯出來
  jsoup是一個很好用的套件,其實他可以運用的功能很多,這裡只是冰山一角而已,至於想要如何呈現或是在資料中得知有用的資訊又是一項艱難的任務了。
  所以這是為什麼資料分析會那麼火紅的原因之一,小弟不是做資料分析的,但是在爬資料的時候都有先預設說爬什麼資料與想知道什麼資訊,從爬到的資料中尋找出我想知道的答案,所以大家也可以想想,自己手上的資料是否也有貨真價實的資訊等著我們發覺、探究和解惑。