
在 Java 程式中,要存取 HTTP 資料通常很麻煩,需要好幾行才能搞定。
URL url = new URL("http://google.com");
URLConnection conn = url.openConnection();
//...略
如果要做到進階的網頁資源存取,一個簡單的動作有可能需要用上錯綜複雜的程式碼。一般來說,Java 開發者會先加入 Apache Commons HttpClient 這個套件,來補強 Java 內建網路相關類別功能不足。
由於 Java 實在太麻煩,我們就別浪費時間看它怎麼做。
在 Groovy 的世界中,存取網頁原始碼最短只需要一行:
new URL('http://google.com').text
實際上在存取網頁時,我們需要加上 GET / POST 的參數資料,設定 HTTP Header 以及判斷伺服器的回傳的代碼等;如果加上這些考量,就需要額外的函式庫輔助才行。在 Groovy 程式設計中;Builder 是一個相當棒的設計,它可以讓一段比較複雜的程式碼用清楚表達的描述語言來撰寫,例如 HttpBuilder 官方的範例:
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.6' )
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
def http = new HTTPBuilder( 'http://ajax.googleapis.com' )
http.request( GET, JSON ) {
uri.path = '/ajax/services/search/web'
uri.query = [ v:'1.0', q: 'Calvin and Hobbes' ]
headers.'User-Agent' = 'Mozilla/5.0 Ubuntu/8.10 Firefox/3.0.4'
response.success = { resp, json ->
println resp.statusLine
json.responseData.results.each {
println " ${it.titleNoFormatting} : ${it.visibleUrl}"
}
}
response.failure = { resp ->
println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}"
}
}
上面這段程式碼存取 Google 搜尋的 API,設定了 v 與 q 兩個參數,也依照伺服器回傳結果,依照 success(通常代碼為 200)或 failure(例如 404 錯誤),分別執行不同的處理(利用 Groovy 的 Closure 撰寫)。這個範例也設定了 HTTP Request Header,在送出請求時偽裝成 Ubuntu 下的 Firefox 瀏覽器(雖然這個偽裝很鳥);比較特別的地方,在於我們不僅指定 HTTP 請求方式為 GET,同時也指定回傳資料類型為 JSON。
由於 Groovy 本身已支援 JSON 的資料結構,所以回傳的結果 json 變數,可以直接透過 json.titleNoFormatting 這樣的方式取得 value。
將 http.request 的回傳資料類型改成 HTML,傳回的結果 html 變數,就是 Groovy Slurper 解析過的 NodeChild 物件,可以進一步存取標籤的值(範例是取得 <head> 中 <title> 標籤的標題文字)。
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.6' )
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
def http = new HTTPBuilder( 'http://google.com' )
http.request( GET, HTML ) {
uri.path = '/search'
uri.query = [ q: '蘋果' ]
headers.'User-Agent' = 'Mozilla/5.0 .................'
response.success = { resp, html ->
println resp.statusLine
println html.HEAD.TITLE
}
response.failure = { resp ->
println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}"
}
}
沒有留言:
張貼留言