Java学习之利用yahoo weather api 获取天气预报 » 荒野无灯weblog

Keep It Simple, Stupid.

荒野无灯weblog

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

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

The zip file below contains a license file, a readme file, and three data files in tab-delineated, Unicode (UTF-8) format:
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来搞定它吧。

CREATE USER 'geoplanet'@'localhost' IDENTIFIED BY 'geoplanet';

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 ;

CREATE DATABASE IF NOT EXISTS `geoplanet` ;

ALTER DATABASE `geoplanet` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

GRANT ALL PRIVILEGES ON `geoplanet` . * TO 'geoplanet'@'localhost';

FLUSH PRIVILEGES;

CREATE TABLE IF NOT EXISTS `places` (
  `woe_id` varchar(15) NOT NULL,
  `iso` varchar(6) NOT NULL,
  `name` text NOT NULL,
  `language` varchar(6) NOT NULL,
  `placetype` varchar(15) NOT NULL,
  `parent__id` varchar(15) NOT NULL,
  PRIMARY KEY (`woe_id`)
) 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:

use geoplanet;
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;
mysql> use geoplanet
Database changed
mysql> show tables;
+---------------------+
| Tables_in_geoplanet |
+---------------------+
| places              |
+---------------------+
1 row in set (0.00 sec)

mysql> 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写得勉强,见笑了 :smile: ):

package com.ihacklog.java.learn;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;

/**
 * MySQL辅助类
 * @author HuangYe <荒野无灯>
 * @URL http://ihacklog.com
 * @see http://dev.mysql.com/doc/refman/5.5/en/connector-j.html
 */

public class mysql {
    private String server = "localhost";
    private String port = "3306";
    private String user = "geoplanet";
    private String password = "geoplanet";
    private String database = "geoplanet";
    private static Connection conn = null;
    private String query = null;

    public mysql(String server, String port, String user, String password,
            String database) {
        super();
        this.server = server;
        this.port = port;
        this.user = user;
        this.password = password;
        this.database = database;

        try {
            // The newInstance() call is a work around for some
            // broken Java implementations

            Class.forName("com.mysql.jdbc.Driver").newInstance();
            this.connect();
        } catch (Exception ex) {
            // handle the error
        }

    }

    /**
     * create JDBC connection
     * 
     * @return Connection
     */
    public Connection connect() {
        if (null == mysql.conn) {
            try {
                mysql.conn = DriverManager.getConnection("jdbc:mysql://"
                        + this.server + ":" + this.port + "/" + this.database
                        + "?" + "user=" + this.user + "&password="
                        + this.password + "&characterEncoding=utf8");

            } catch (SQLException ex) {
                // handle any errors
                System.out.println("SQLException: " + ex.getMessage());
                System.out.println("SQLState: " + ex.getSQLState());
                System.out.println("VendorError: " + ex.getErrorCode());
            }
        }
        return mysql.conn;
    }

    public String getOneCol(String query,String columnName)
    {
        Statement stmt = null;
        ResultSet rs = null;
        String colString ="";
        this.query = query;
        try{
        stmt = mysql.conn.createStatement();
        rs = stmt.executeQuery(this.query);
        while(rs.next()) {
            colString = rs.getString(columnName);
        }
        }
         catch (SQLException sqlEx) {
            } // ignore

        finally {

            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException ex) {
                    // ignore
                }
            }

            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException ex) {
                    // ignore
                }
            }
        }
         return colString;
    }
}

然后是天气信息查询类:

package com.ihacklog.java.learn;
//For saving XML file
/*import java.io.File;
import java.io.FileOutputStream;*/
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
//For saving XML file
/*import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;*/
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.ihacklog.java.learn.mysql;

/**
 * @author 狼の禅 [http://www.cnblogs.com/kingwolfofsky], HuangYe <荒野无灯>
 *
 */
class GetWeatherInfo {
    private static mysql db= null;
    /**
     * 天气信息代码
     * @see http://developer.yahoo.com/weather/#codes
     */
    private final String[] dictionaryStrings = { "龙卷风", "热带风暴", "飓风", "强雷阵雨",
            "雷阵雨", "小雨加雪", "雨加冰雹", "雪加冰雹", "冰雨", "毛毛雨", "冻雨", "阵雨", "阵雨", "小雪",
            "零星小雪", "高吹雪", "雪", "冰雹", "雨夹雪", "尘", "雾", "薄雾", "多烟的", "大风", "有风",
            "寒冷", "阴天", "夜间阴天", "白天阴天", "夜间多云", "白天多云", "夜间清亮", "晴朗", "转晴",
            "转晴", "雨夹冰雹", "热", "雷阵雨", "雷阵雨", "雷阵雨", "雷阵雨", "大雪", "阵雪", "大雪",
            "多云", "雷", "阵雪", "雷雨" };
    public GetWeatherInfo() {
        GetWeatherInfo.db=new mysql("localhost", "3306", "geoplanet", "geoplanet", "geoplanet");
    }

    private String getCityWOEID(String cityName)
    {
        String woeid = null;
        woeid=GetWeatherInfo.db.getOneCol("SELECT woe_id FROM places WHERE name='"+ cityName + "'","woe_id");
        return woeid;
    }
    /**
     * modified by 荒野无灯
     * @see http://developer.yahoo.com/weather/ 
     * @see http://en.wikipedia.org/wiki/WOEID
     * @see http://developer.yahoo.com/geo/geoplanet/
     * @see http://developer.yahoo.com/geo/geoplanet/data/
     * @param cityCode
     * @return  Document
     * @throws IOException
     */
    private Document getWeatherXML(String cityCode) throws IOException {
        URL url = new URL("http://weather.yahooapis.com/forecastrss?w=" + cityCode + "&u=c");
        URLConnection connection = url.openConnection();
        Document Doc = stringToElement(connection.getInputStream());
        return Doc;
    }
    /* 保存获取的天气信息XML文档 */
/*    private void saveXML(Document Doc, String Path) {
        TransformerFactory transFactory = TransformerFactory.newInstance();
        Transformer transformer;
        try {
            transformer = transFactory.newTransformer();
            DOMSource domSource = new DOMSource(Doc);
            File file = new File(Path);
            FileOutputStream out = new FileOutputStream(file);
            StreamResult xmlResult = new StreamResult(out);
            transformer.transform(domSource, xmlResult);
        } catch (Exception e) {
            System.out.println("保存文件出错!");
        }
    }*/
    /* 获取天气信息 */
    public String getWeather(String city) {
        String result = null;
        try {
            String cityWOEID =getCityWOEID(city);
            if( null == cityWOEID )
                return null;

            Document doc = getWeatherXML( cityWOEID );
            NodeList nodeList = doc.getElementsByTagName("channel");
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                NodeList nodeList1 = node.getChildNodes();
                for (int j = 0; j < nodeList1.getLength(); j++) {
                    Node node1 = nodeList1.item(j);
                    if (node1.getNodeName().equalsIgnoreCase("item")) {
                        NodeList nodeList2 = node1.getChildNodes();
                        for (int k = 0; k < nodeList2.getLength(); k++) {
                            Node node2 = nodeList2.item(k);
                            if (node2.getNodeName().equalsIgnoreCase(
                                    "yweather:forecast")) {
                                NamedNodeMap nodeMap = node2.getAttributes();
                                Node lowNode = nodeMap.getNamedItem("low");
                                Node highNode = nodeMap.getNamedItem("high");
                                Node codeNode = nodeMap.getNamedItem("code");
                                String day = "\n明天";
                                if (result == null) {
                                    result = "城市:" + city ;
                                    day = "\n今天";
                                } else {
                                    day = "\n明天";
                                }
                                result = result
                                        + day
                                        + " "
                                        + dictionaryStrings[Integer
                                                .parseInt(codeNode
                                                        .getNodeValue())]
                                        + "\t最低温度:" + lowNode.getNodeValue()
                                        + "℃ \t最高温度:" + highNode.getNodeValue()
                                        + "℃ ";
                            }
                        }
                    }
                }
            }
            //save file JUST for DEBUG
//            saveXML(doc, "D:\\tmp\\Weather.xml");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    public Document stringToElement(InputStream input) {
        try {
            DocumentBuilder db = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder();
            Document doc = db.parse(input);
            return doc;
        } catch (Exception e) {
            return null;
        }
    }
}

测试:

package com.ihacklog.java.learn;
import com.ihacklog.java.learn.GetWeatherInfo;

/**
 * @author HuangYe <荒野无灯>
 * @URL http://ihacklog.com
 */
public class getWeather {
    public static void main(String arg[]) {

        //OK,let's begin the test.
        //Have fun!
        GetWeatherInfo info = new GetWeatherInfo();
        String weather = info.getWeather("岳阳市");
        System.out.println(weather);

        weather = info.getWeather("哈尔滨");
        System.out.println(weather);

        weather = info.getWeather("海口市");
        System.out.println(weather);

        weather = info.getWeather("长沙市");
        System.out.println(weather);

        weather = info.getWeather("武汉市");
        System.out.println(weather);
    }
}

本文参考文档:
Importing GeoPlanet data into MySQL
Java获取yahoo天气预报
JDBC and MySQL: Run the Programs
Yahoo! GeoPlanet Guide

Yahoo! GeoPlanet™ Data


Yahoo! Weather RSS Feed docs

Tagged in :

All Comments (0)
Gravatar image
No Comments