一、聚合数据WebService介绍
聚合数据(https://www.juhe.cn/),是一个专门提供各种数据服务网站。使用之前需要先注册成为开发者。
二、聚合数据WebService服务使用
1.注册成为聚合数据服务开发者。(如果已有账户,则可跳过此步,直接进入登录界面进行登录)
步骤:
(1)在浏览器地址框中输入或复制聚合数据官方网址:https://www.juhe.cn/,回车,打开聚合数据网站。
(2)点击聚合数据网站右上角的注册文本,进入注册界面。
(3)按照界面上的注册向导,完成注册。
(4)使用新注册账户进行登录成功后,方可有权使用聚合数据服务。
2、申请全国天气预报数据API服务(测试使用2个月,之后需要对app进行审核,否则数据服务不能正常使用)
步骤:
(1)初始登录是直接进入个人中心的,可在个人中心申请数据服务,如下图:
(2)如果不是初始登录,则进入首页,可按下图步骤申请全国天气预报数据服务:
(2)点击申请数据按钮,进入申请数据界面。
(3)点击申请按钮,完成申请。
如果是第一次注册,需要输入手机号码,如果是已经申请过此服务,则提醒已经申请过该服务了
3、查看我的数据。
已经申请过的数据服务,在我的数据界面会以列表的方式一条一条的显示该界面中。
步骤:
(1)点击左侧数据中心里我的数据,会看到刚刚申请成功的全国天气预报记录,
可能会有其它申请过的数据服务记录。
(2)点击操作列的查看,可以查看应用信息,尤其AppKey,它作为数据服务识别我们的APP的唯一标识。
(3)点击操作列的统计,可以查看我们的APP今日和近15天内每小时请求数走势图。
刚申请时没有请求数据,所以走势图为空是正常的。
如果有请求数据,则统计就会以折线的方式展示,如下图:
4、学习API
步骤:
(1)在我的数据中,点击全国天气预报记录的操作列中接口文本,进入接口文档界面。
目前支持6个接口,根据需求使用对应的API。
(2)根据城市名/id查询天气接口研究。
此接口将作为我们获取某城市天气数据的接口。
接口文档描述的非常清楚,这里就不重复了。如有问题,大家可在留言处提问或私信我。
(3)天气种类及标识列表接口研究。
此接口将天气与一个标识一一对应,将来可作为匹配天气对应的图标标识。
接口文档描述的非常清楚,这里就不重复了。如有问题,大家可在留言处提问或私信我。
(4)支持城市列表接口研究。
此接口将作为我们更多城市模块中要使用城市数据的接口。
接口文档描述的非常清楚,这里就不重复了。如有问题,大家可在留言处提问或私信我。
4、测试API
聚合平台提供了测试每个API的测试工具,我们可以通过测试工具来测试要使用的接口是否正常。
步骤:
(1)点击API界面中的API测试工具文本,进入测试工具界面。
(2)测试:
根据城市名/id查询天气接口。(第一个API)
如果返回的结果下如图,说明申请的数据服务时间上已超过聚合设定的测试模式使用时间,需要实名认证
后才可继续使用此数据服务。
如需实名认证可进入个人中心,点击个人资料中的实名认证,按要求填写姓名和上传身份证正反面,再点击提交 认 证,完成认证
(一般在一小时内通知认证结果)。
如果没有以上问题,测试结果应该如下图:
测试结果如下图:
(4)测试其它接口
如果需要用到其它接口,可类似上面两个测试接口的步骤进行测试。
5、编码实现数据的获取
全国天气预报API中有各种语言编写的示例代码,可参考这里的示例完成数据的获取(我选择Java语言)。
需要注意的是:如果获取数据时,返回的状态码不是200,可根据API中的错误码对照表查找错误原因。
下面是示例代码中的一些核心代码:
(1)常量工具类:
package com.kedi.juheclient.constant;
/**
* 常量池对象类:专门用来存放APP中要使用到的常量
*
* @author 张科勇
*
*/
public class AppConstant {
// 聚合数据-申请数据服务成功后分配的key,做为此应用与数据服务交互的唯一标识
public static final String APPKEY = "01360343b6a3ca6d4ade944eee95bf96";
// 根据城市名获取天气数据的网络地址
public static final String WEATHER_REPORT_BY_CITY_URL = "http://v.juhe.cn/weather/index";
// 获取天气种类及标识列表网络地址
public static final String WEATHER_ICON_AND_ID_URL = "http://v.juhe.cn/weather/uni";
// 获取支持城市列表网络地址
public static final String CITY_LIST_URL = "http://v.juhe.cn/weather/citys";
// 表示数据获取功能
public static final String RESULT_OK = "200";
}
(2)获取网络数据工具类
package com.kedi.juheclient.utils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
/**
* 网络请求工具类
*
* @author 张科勇
*
*/
public class NetWorkUtil {
/**
* get方式请求网络数据的方法
*
* @param url
* 网络地址
* @return 网络数据
*/
public static <K, V> String get(String url) {
try {
// 将字符串网址封装成URL对象,目前是为了使用URL对象打开网络链接
URL u = new URL(url);
// 打开网络链接,并强制转化成使用Http协议的链接对象HttpURLConnection
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
StringBuffer sb = null;
conn.setRequestMethod("GET");
conn.connect();// 建立连接
// 获取服务端响应码,如果等于200,则服务端响应成功,否则响应不成功
int recode = conn.getResponseCode();
// 服务端响应请求成功
if (recode == HttpsURLConnection.HTTP_OK) {
// 获取输入流(字节流),读取服务端返回的数据
InputStream in = conn.getInputStream();
// 将字节流转化成字符流
InputStreamReader inr = new InputStreamReader(in);
// 将低级流封装成高级流
BufferedReader br = new BufferedReader(inr);
String str = null;
sb = new StringBuffer();
// 按行读取服务端返回的数据,判断如果不为null,则将读到的一行数据保存到StringBuffer中
while ((str = br.readLine()) != null) {
sb.append(str);
// 每行后添加一个换行符
sb.append(System.getProperty("line.separator"));
}
// 关闭输入流
br.close();
// 判断如果返回的数据为空,返回null
if (sb.toString().length() == 0) {
// 获取的数据为空
return null;
}
// 返回服务端响应的数据字符串(去到最后一行的换行符)
return sb.toString().substring(0,
sb.toString().length() - System.getProperty("line.separator").length());
}
return null;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* post方式请求网络数据的方法
*
* @param url
* 网络地址
* @param params
* 请求参数Map集合,如果没有参数,则传null
* @return 返回网络数据
*/
public static <K, V> String post(String url, Map<K, V> params) {
try {
// 将字符串网址封装成URL对象,目前是为了使用URL对象打开网络链接
URL u = new URL(url);
// 打开网络链接,并强制转化成使用Http协议的链接对象HttpURLConnection
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
StringBuffer sb = null;
// 判断网络请求是否带参数,如果带参数则params!=null,接下来需要将参数从Map集合中遍历出来,写到输出流中
if (params != null) {
// 打开输出流开闭,默认是关闭的,只有打开后,客户端才可以通过输出流向服务端上传数据(此处上传的是参数数据)
conn.setDoOutput(true);
// 设置请求方式为post
conn.setRequestMethod("POST");
// 获取输出流对象(字节流)
OutputStream out = conn.getOutputStream();
// 将字节流转化成字符流
OutputStreamWriter ousw = new OutputStreamWriter(out);
// 将低级流转化成带缓冲的高级流
BufferedWriter bw = new BufferedWriter(ousw);
sb = new StringBuffer();
// 遍历Map集合中的所有参数,并按k=v&的形式保存到StringBuffer中
for (Map.Entry<K, V> m : params.entrySet()) {
sb.append(m.getKey() + "=" + m.getValue() + "&");
}
// 使用高级流将StringBuffer中的参数写到输出流中
bw.write(sb.deleteCharAt(sb.length() - 1).toString());
// 关闭高级输出流,将参数上传给服务端
bw.close();
sb = null;
}
conn.connect();// 建立连接
// 获取服务端响应码,如果等于200,则服务端响应成功,否则响应不成功
int recode = conn.getResponseCode();
// 服务端响应请求成功
if (recode == HttpsURLConnection.HTTP_OK) {
// 获取输入流(字节流),读取服务端返回的数据
InputStream in = conn.getInputStream();
// 将字节流转化成字符流
InputStreamReader inr = new InputStreamReader(in);
// 将低级流封装成高级流
BufferedReader br = new BufferedReader(inr);
String str = null;
sb = new StringBuffer();
// 按行读取服务端返回的数据,判断如果不为null,则将读到的一行数据保存到StringBuffer中
while ((str = br.readLine()) != null) {
sb.append(str);
// 每行后添加一个换行符
sb.append(System.getProperty("line.separator"));
}
// 关闭输入流
br.close();
// 判断如果返回的数据为空,返回null
if (sb.toString().length() == 0) {
// 获取的数据为空
return null;
}
// 返回服务端响应的数据字符串(去到最后一行的换行符)
return sb.toString().substring(0,
sb.toString().length() - System.getProperty("line.separator").length());
}
return null;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
(3)获取天气相关数据工具类
package com.kedi.juheclient.utils;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import com.kedi.juheclient.constant.AppConstant;
import android.util.Log;
/**
* 获取天气相对数据的工具类
*
* @author 张科勇
*
*/
public class WeatherReportUtil {
/**
* 根据城市名获取天气数据的方法
*
* @param cityName
* 城市名, 必填
* @param dtype
* 返回数据格式:json或xml,默认json,可选
* @param format
* 未来6天预报(future)两种返回格式,1或2,默认1,可选
* @return
*/
public static String getWeatherReportByCity(String cityName, String dtype, int format) {
// 接口网址
String url = AppConstant.WEATHER_REPORT_BY_CITY_URL;
StringBuffer sb = new StringBuffer();
String city;
try {
// 将传递进来的中文使用UTF-8进行编码
city = URLEncoder.encode(cityName, "utf-8");
// 拼装url
sb.append("cityname=" + city);
sb.append("&");
sb.append("format=" + format);
sb.append("&");
sb.append("dtype=" + dtype);
sb.append("&");
sb.append("key=" + AppConstant.APPKEY);
url = url + "?" + sb.toString();
// 这里用get方式请求数据
String result = NetWorkUtil.get(url);
JSONObject jsonObj = new JSONObject(result);
// 安全性检查
if (!"".equals(jsonObj)) {
String resultcode = jsonObj.getString("resultcode");
if (!"".equals(resultcode)) {
if (AppConstant.RESULT_OK.equals(resultcode)) {
result = jsonObj.getString("result");
return result;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取支持的城市列表数据
*
* @param dtype
* 返回数据格式:json或xml,默认json,可选
* @return
*/
public static String getCityList(String dtype) {
// 拼装url
String url = AppConstant.CITY_LIST_URL;
Map<String, String> params = new HashMap<String, String>();
params.put("dtype", dtype);
params.put("key", AppConstant.APPKEY);
// 用post方式请求数据
String result = NetWorkUtil.post(url, params);
JSONObject jsonObj;
try {
jsonObj = new JSONObject(result);
String resultcode = jsonObj.getString("resultcode");
if (AppConstant.RESULT_OK.equals(resultcode)) {
result = jsonObj.getString("result");
return result;
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取天气种类及标识列表数据
*
* @param dtype
* 返回数据格式:json或xml,默认json,可选
* @return
*/
public static String getWeatherIconAndId(String dtype) {
// 拼装url
String url = AppConstant.WEATHER_ICON_AND_ID_URL;
Map<String, String> params = new HashMap<String, String>();
params.put("dtype", dtype);
params.put("key", AppConstant.APPKEY);
// 用post方式请求数据
String result = NetWorkUtil.post(url, params);
JSONObject jsonObj;
try {
jsonObj = new JSONObject(result);
String resultcode = jsonObj.getString("resultcode");
if (AppConstant.RESULT_OK.equals(resultcode)) {
result = jsonObj.getString("result");
return result;
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
(4)测试代码
package com.kedi.juheclient;
import com.kedi.juheclient.utils.WeatherReportUtil;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
/**
* 测试类
* @author 张科勇
*
*/
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
// 根据城市名获取天气数据
String weatherStr = WeatherReportUtil.getWeatherReportByCity("北京", "json", 2);
Log.i("weatherStr=", weatherStr + "");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// 获取天气图标与标识
String weatherIconAndIdStr = WeatherReportUtil.getWeatherIconAndId("json");
Log.i("weatherIconAndIdStr=", weatherIconAndIdStr + "");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// 获取支持城市列表数据
String cityListStr = WeatherReportUtil.getCityList("json");
Log.i("cityListStr=", cityListStr + "");
}
}).start();
}
}
说明:这是一个Android项目,不要忘了在AndroidManifest.xml文件中添加访问网络的权限。
案例源码下载:http://pan.baidu.com/s/1dEjE7Rz