荒野无灯

just another weblog of 荒野无灯

导航

Java学习之利用yahoo weather api 获取天气预报

在cnblogs看到 狼の禅 写的Java获取yahoo天气预报一文,于是有了这篇文章。
狼の禅 是将<地点代码,地名> 对用HashMap 来保存在类中的,发现手动查找地点代码然后要一个个加进去还真麻烦,于是想下有没有偷懒的办法。果然,在雅虎 geoplanet 找到了答案。
最简单的办法是申请一个yahoo dev 的key ,然后就可以通过 GeoPlanet api 来查询相应地点的WOEID了。
狼の禅 用的是旧的p 参数传递地点代码,不过最新的api文档里面只对w参数作了说明,因此这里我就用WOEID了。
不想注册申请key,还是自己折腾吧。
下载最新的 GeoPlanet Data ,解压出来有这些个文件:

geoplanet_places_[version].tsv: the WOEID, the placename, and the WOEID of its parent entity
geoplanet_aliases_[version].tsv: alternate names in multiple languages indexed against the WOEID
geoplanet_adjacencies_[version].tsv: the entities neighboring each WOEID
geoplanet_changes_[version].tsv: the list of removed WOEIDs and their replacement WOEID mappings 

 这里我只取 geoplanet_places_7.6.0.tsv ,用EmEditor 打开,把 中国 地区的 COPY 出到另外一个文件Chinaplaces.tsv .
这个tsv 文件是用tab分隔字段的,places文件的字段有:

WOE_ID ISO Name Language PlaceType Parent_ID 

 直接解析这个tsv文件不怎么方便和高效,还是用MySQL来搞定它吧。

 1 CREATE USER 'geoplanet'@'localhost' IDENTIFIED BY 'geoplanet';
2
3 GRANT USAGE ON * . * TO 'geoplanet'@'localhost' IDENTIFIED BY 'geoplanet' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
4
5 CREATE DATABASE IF NOT EXISTS `geoplanet` ;
6
7 ALTER DATABASE `geoplanet` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
8
9 GRANT ALL PRIVILEGES ON `geoplanet` . * TO 'geoplanet'@'localhost';
10
11 FLUSH PRIVILEGES;
12
13 CREATE TABLE IF NOT EXISTS `places` (
14 `woe_id` varchar(15) NOT NULL,
15 `iso` varchar(6) NOT NULL,
16 `name` text NOT NULL,
17 `language` varchar(6) NOT NULL,
18 `placetype` varchar(15) NOT NULL,
19 `parent__id` varchar(15) NOT NULL,
20 PRIMARY KEY (`woe_id`)
21 ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

 然后,导入之( geoplanet 为数据库名):

mysqlimport –ignore-lines=1 –fields-optionally-enclosed-by=’”‘ –fields-terminated-by=\t” –user=”root” –password –local geoplanet places.tsv


  或者直接进mysql:

1 use geoplanet;
2 LOAD DATA LOCAL INFILE 'D:\\code\\java\\geoplanet_data_7.6.0\\Chinaplaces.tsv' INTO TABLE `places` FIELDS TERMINATED BY '\t' ENCLOSED BY '"' ESCAPED BY '\' LINES TERMINATED BY '\n' IGNORE 1 LINES;

导入成功后会显示:

Query OK, 10519 rows affected (0.26 sec)
Records: 10519 Deleted: 0 Skipped: 0 Warnings: 0

然后就是连接mysql啦(java目前我也就写过一个hello world, class写得勉强,见笑了 ):

  1 package com.ihacklog.java.learn;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.SQLException;
6 import java.sql.Statement;
7 import java.sql.ResultSet;
8 //import java.util.Arrays;
9
10 /**
11 * MySQL辅助类
12 * @author HuangYe <荒野无灯>
13 * @URL http://ihacklog.com
14 * @see http://dev.mysql.com/doc/refman/5.5/en/connector-j.html
15 */
16
17 public class mysql {
18 private String server = "localhost";
19 private String port = "3306";
20 private String user = "geoplanet";
21 private String password = "geoplanet";
22 private String database = "geoplanet";
23 private static Connection conn = null;
24 private String query = null;
25
26 public mysql(String server, String port, String user, String password,
27 String database) {
28 super();
29 this.server = server;
30 this.port = port;
31 this.user = user;
32 this.password = password;
33 this.database = database;
34
35 try {
36 // The newInstance() call is a work around for some
37 // broken Java implementations
38
39 Class.forName("com.mysql.jdbc.Driver").newInstance();
40 this.connect();
41 } catch (Exception ex) {
42 // handle the error
43 }
44
45 }
46
47 /**
48 * create JDBC connection
49 *
50 * @return Connection
51 */
52 public Connection connect() {
53 if (null == mysql.conn) {
54 try {
55 mysql.conn = DriverManager.getConnection("jdbc:mysql://"
56 + this.server + ":" + this.port + "/" + this.database
57 + "?" + "user=" + this.user + "&password="
58 + this.password + "&characterEncoding=utf8");
59
60 } catch (SQLException ex) {
61 // handle any errors
62 System.out.println("SQLException: " + ex.getMessage());
63 System.out.println("SQLState: " + ex.getSQLState());
64 System.out.println("VendorError: " + ex.getErrorCode());
65 }
66 }
67 return mysql.conn;
68 }
69
70
71 String getOneCol(String query,String columnName)
72 {
73 Statement stmt = null;
74 ResultSet rs = null;
75 String colString ="";
76 this.query = query;
77 try{
78 stmt = mysql.conn.createStatement();
79 rs = stmt.executeQuery(this.query);
80 while(rs.next()) {
81 colString = rs.getString(columnName);
82 }
83 }
84 catch (SQLException sqlEx) {
85 } // ignore
86
87 finally {
88
89 if (rs != null) {
90 try {
91 rs.close();
92 } catch (SQLException ex) {
93 // ignore
94 }
95 }
96
97 if (stmt != null) {
98 try {
99 stmt.close();
100 } catch (SQLException ex) {
101 // ignore
102 }
103 }
104 }
105 return colString;
106 }
107 }

 然后是天气信息查询类:

View Code
  1 package com.ihacklog.java.learn;
2
3 //For saving XML file
4 /*import java.io.File;
5 import java.io.FileOutputStream;*/
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.net.URL;
9 import java.net.URLConnection;
10 import javax.xml.parsers.DocumentBuilder;
11 import javax.xml.parsers.DocumentBuilderFactory;
12 //For saving XML file
13 /*import javax.xml.transform.Transformer;
14 import javax.xml.transform.TransformerFactory;
15 import javax.xml.transform.dom.DOMSource;
16 import javax.xml.transform.stream.StreamResult;*/
17 import org.w3c.dom.Document;
18 import org.w3c.dom.NamedNodeMap;
19 import org.w3c.dom.Node;
20 import org.w3c.dom.NodeList;
21 import com.ihacklog.java.learn.mysql;
22
23 /**
24 * @author 狼の禅 [http://www.cnblogs.com/kingwolfofsky], HuangYe <荒野无灯>
25 *
26 */
27 class GetWeatherInfo {
28 private static mysql db = null;
29 /**
30 * 天气信息代码
31 *
32 * @see http://developer.yahoo.com/weather/#codes
33 */
34 private final String[] dictionaryStrings = { "龙卷风", "热带风暴", "飓风", "强雷阵雨",
35 "雷阵雨", "小雨加雪", "雨加冰雹", "雪加冰雹", "冰雨", "毛毛雨", "冻雨", "阵雨", "阵雨", "小雪",
36 "零星小雪", "高吹雪", "", "冰雹", "雨夹雪", "", "", "薄雾", "多烟的", "大风", "有风",
37 "寒冷", "阴天", "夜间阴天", "白天阴天", "夜间多云", "白天多云", "夜间清亮", "晴朗", "转晴",
38 "转晴", "雨夹冰雹", "", "雷阵雨", "雷阵雨", "雷阵雨", "雷阵雨", "大雪", "阵雪", "大雪",
39 "多云", "", "阵雪", "雷雨" };
40
41 public GetWeatherInfo() {
42 GetWeatherInfo.db = new mysql("localhost", "3306", "geoplanet",
43 "geoplanet", "geoplanet");
44 }
45
46 private String getCityWOEID(String cityName) {
47 String woeid = null;
48 woeid = GetWeatherInfo.db.getOneCol(
49 "SELECT woe_id FROM places WHERE name='" + cityName + "'",
50 "woe_id");
51 return woeid;
52 }
53
54 /**
55 * modified by 荒野无灯
56 *
57 * @see http://developer.yahoo.com/weather/
58 * @see http://en.wikipedia.org/wiki/WOEID
59 * @see http://developer.yahoo.com/geo/geoplanet/
60 * @see http://developer.yahoo.com/geo/geoplanet/data/
61 * @param cityCode
62 * @return Document
63 * @throws IOException
64 */
65 private Document getWeatherXML(String cityCode) throws IOException {
66 URL url = new URL("http://weather.yahooapis.com/forecastrss?w="
67 + cityCode + "&u=c");
68 URLConnection connection = url.openConnection();
69 Document Doc = stringToElement(connection.getInputStream());
70 return Doc;
71 }
72
73 /* 保存获取的天气信息XML文档 */
74 /*
75 * private void saveXML(Document Doc, String Path) { TransformerFactory
76 * transFactory = TransformerFactory.newInstance(); Transformer transformer;
77 * try { transformer = transFactory.newTransformer(); DOMSource domSource =
78 * new DOMSource(Doc); File file = new File(Path); FileOutputStream out =
79 * new FileOutputStream(file); StreamResult xmlResult = new
80 * StreamResult(out); transformer.transform(domSource, xmlResult); } catch
81 * (Exception e) { System.out.println("保存文件出错!"); } }
82 */
83 /* 获取天气信息 */
84 public String getWeather(String city) {
85 String result = null;
86 try {
87 String cityWOEID = getCityWOEID(city);
88 if (null == cityWOEID)
89 return null;
90
91 Document doc = getWeatherXML(cityWOEID);
92 NodeList nodeList = doc.getElementsByTagName("channel");
93 for (int i = 0; i < nodeList.getLength(); i++) {
94 Node node = nodeList.item(i);
95 NodeList nodeList1 = node.getChildNodes();
96 for (int j = 0; j < nodeList1.getLength(); j++) {
97 Node node1 = nodeList1.item(j);
98 if (node1.getNodeName().equalsIgnoreCase("item")) {
99 NodeList nodeList2 = node1.getChildNodes();
100 for (int k = 0; k < nodeList2.getLength(); k++) {
101 Node node2 = nodeList2.item(k);
102 if (node2.getNodeName().equalsIgnoreCase(
103 "yweather:forecast")) {
104 NamedNodeMap nodeMap = node2.getAttributes();
105 Node lowNode = nodeMap.getNamedItem("low");
106 Node highNode = nodeMap.getNamedItem("high");
107 Node codeNode = nodeMap.getNamedItem("code");
108 String day = "\n明天";
109 if (result == null) {
110 result = "城市:" + city;
111 day = "\n今天";
112 } else {
113 day = "\n明天";
114 }
115 result = result
116 + day
117 + " "
118 + dictionaryStrings[Integer
119 .parseInt(codeNode
120 .getNodeValue())]
121 + "\t最低温度:" + lowNode.getNodeValue()
122 + "℃ \t最高温度:" + highNode.getNodeValue()
123 + "";
124 }
125 }
126 }
127 }
128 }
129 // save file JUST for DEBUG
130 // saveXML(doc, "D:\\tmp\\Weather.xml");
131 } catch (Exception e) {
132 e.printStackTrace();
133 }
134 return result;
135 }
136
137 public Document stringToElement(InputStream input) {
138 try {
139 DocumentBuilder db = DocumentBuilderFactory.newInstance()
140 .newDocumentBuilder();
141 Document doc = db.parse(input);
142 return doc;
143 } catch (Exception e) {
144 return null;
145 }
146 }
147 }

测试一下:

View Code
 1 package com.ihacklog.java.learn;
2
3 import com.ihacklog.java.learn.GetWeatherInfo;
4
5 /**
6 * @author HuangYe <荒野无灯>
7 * @URL http://ihacklog.com
8 */
9 public class getWeather {
10 public static void main(String arg[]) {
11
12 // OK,let's begin the test.
13 // Have fun!
14 GetWeatherInfo info = new GetWeatherInfo();
15 String weather = info.getWeather("岳阳市");
16 System.out.println(weather);
17
18 weather = info.getWeather("哈尔滨");
19 System.out.println(weather);
20
21 weather = info.getWeather("海口市");
22 System.out.println(weather);
23
24 weather = info.getWeather("长沙市");
25 System.out.println(weather);
26
27 weather = info.getWeather("武汉市");
28 System.out.println(weather);
29 }
30 }

 本文参考文档:

Java获取yahoo天气预报 

最初发布在:

http://ihacklog.com/?p=4684 

posted on 2011-07-24 16:47  荒野无灯  阅读(2258)  评论(3编辑  收藏  举报

Copyright © 2011 荒野无灯     Thanks 博客园    Top↑
声明: 本博遵循 署名-非商业性使用-相同方式共享 2.5 共享协议. 转载请注明出处并标明URL。