【目的】
- 讀取 Google Weather。
【原理】
- Google Weather 提供多樣化的API查詢方式
- 透過 程式名稱 查詢天氣(以台北為例)
http://www.google.com/ig/api?hl=zh_tw&weather=taipei - 透過 郵遞區號(不過這在台灣並不適用,10466原本是台北市中山區,但會變成Bronx, NY)
http://www.google.com/ig/api?hl=zh-tw&weather=10466 - 透過 城市座標查詢天氣(須符合定義於下方API的座標)
http://www.google.com/ig/api?hl=zh-tw&weather=,,,25091075,121559834 - 查詢台灣所有城市座標(回傳JSON或XML格式)
- 其它方式請參考官方文件
- 透過 程式名稱 查詢天氣(以台北為例)
- Xml 結點與資料(1)
- Xml 結點與資料(2),以 2010年 9月 29 日(禮拜三)為例
- xml_api_reply version=1 (第一層)
- weather module_id=0 tab_id=0 mobile_row=0 mobile_zipped=1 row=0 section=0
- forecast_information 預測資料 (第三層)
- city data=taipei (第四層)
- postal_code data=taipei
- latitude_e6 data=
- forecast_date=2010-09-29
- current_date_time data=2010-09-29 14:00:00 +0000
- unit_system data=SI
- current_conditions 目前狀況 ( 猜測是代表目前時間,比如說 11:00am時的天氣)
- condition data=多雲
- temp_f data=79
- temp_c data=26
- humidity data=濕度: 86%
- icon data=/ig/images/weather/cloudy.gif
- wind_condition data=風向: 公里/小時
- forecast_conditions 預測狀況(這周的天氣預測)
- day_of_week data=週三
- low data=23
- high data=28
- icon data=/ig/images/weather/rain.gif
- condition data=多雲時陰短暫雨
- forecast_conditions 預測狀況
- day_of_week data=週四
- low data=23
- high data=29
- icon data=/ig/images/weather/rain.gif
- condition data=多雲短暫雨
- forecast_conditions 預測狀況
- day_of_week data=週五
- low data=24
- high data=32
- icon data=/ig/images/weather/cloudy.gif
- condition data=多雲
- forecast_conditions 預測狀況
- day_of_week data=週六
- low data=24
- high data=33
- icon data=/ig/images/weather/cloudy.gif
- condition data=多雲
- forecast_information 預測資料 (第三層)
- weather module_id=0 tab_id=0 mobile_row=0 mobile_zipped=1 row=0 section=0
- xml_api_reply version=1 (第一層)
- Xml 格式資料可透過幾種方式讀取
- SAX(Simple API for XML) XML資料唯獨,讀取速度較快
- DOM(Document Object Model) 可更新 XML 資料
- Pull Parse(Java推薦方式,目前Qt 不支援)
【程式】
- main.c 一樣用之前的 QHttp 範例,main.c 中有兩個地方需特別注意
- 抓取資料的網址改成由原本的zh_tw以us顯示,方便處理
http://www.google.com/ig/api?hl=us&weather=taipei
- 抓取網頁成功之後的callback function binding 到 show_weather
int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; w.show(); HttpGet getter; QUrl url("http://www.google.com/ig/api?hl=us&weather=taipei"); getter.downloadFile(QUrl(url)); QObject::connect(&getter, SIGNAL(finished()), &w, SLOT(show_weather())); return a.exec(); }
- 抓取資料的網址改成由原本的zh_tw以us顯示,方便處理
-
由於我們不需更改資料,所以以 SAX 先作實驗
(tbd) -
透過 DOM 的方式 (通常可用 QTreeWidgetItem搭配遞迴方式載入,此處使用苦工方式一個一個讀出)
-
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QUrl> #include "HttpGet.h" #include <iostream> #include <QtXml> #include <QFile> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); protected: void changeEvent(QEvent *e); private: Ui::Dialog *ui; private slots: void show_weather(); void show_forecast_information(const QDomNode node3); void show_current_conditions(const QDomNode node3); void show_forecast_conditions(const QDomNode node3); }; #endif // DIALOG_H
-
dialog.cpp
void Dialog::show_weather() { QDomDocument doc; QFile file("api"); QString errorStr; int errorLine; int errorCol; if(!doc.setContent(&file,true,&errorStr,&errorLine,&errorCol)){ qDebug() << "Unable to open the file"; return; } file.close(); QDomElement root = doc.documentElement(); if (root.tagName() != "xml_api_reply") return; QDomNode node2 = root.firstChild(); if(node2.toElement().tagName() == "weather") { QDomNode node3 = node2.firstChild(); while (!node3.isNull()){ qDebug() << "-" << node3.toElement().tagName(); if(node3.toElement().tagName() == "forecast_information") show_forecast_information(node3); else if (node3.toElement().tagName() == "current_conditions") show_current_conditions(node3); else if (node3.toElement().tagName() == "forecast_conditions") show_forecast_conditions(node3); node3 = node3.nextSibling(); } } } void Dialog::show_forecast_information(const QDomNode node3) { QDomNode node4 = node3.firstChild(); while (!node4.isNull()){ if(node4.toElement().tagName() == "city") qDebug() << " +city:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "postal_code") qDebug() << " +postal_code:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "latitude_e6") qDebug() << " +latitude_e6:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "forecast_date") qDebug() << " +forecast_date:" << node4.toElement().attribute("humidity"); else if(node4.toElement().tagName() == "current_date_time") qDebug() << " +current_date_time:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "unit_system") qDebug() << " +unit_system:" << node4.toElement().attribute("data"); node4 = node4.nextSibling(); } } void Dialog::show_current_conditions(const QDomNode node3) { QDomNode node4 = node3.firstChild(); while (!node4.isNull()){ if(node4.toElement().tagName() == "condition") qDebug() << " +condition:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "temp_f") qDebug() << " +temp_f:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "temp_c") qDebug() << " +temp_c:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "humidity") qDebug() << " +humidity:" << node4.toElement().attribute("humidity"); else if(node4.toElement().tagName() == "icon") qDebug() << " +icon:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "wind_condition") qDebug() << " +wind_condition:" << node4.toElement().attribute("data"); node4 = node4.nextSibling(); } } void Dialog::show_forecast_conditions(const QDomNode node3) { QDomNode node4 = node3.firstChild(); while (!node4.isNull()){ if(node4.toElement().tagName() == "day_of_week") qDebug() << " +day_of_week:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "low") qDebug() << " +low:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "high") qDebug() << " +high:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "icon") qDebug() << " +icon:" << node4.toElement().attribute("data"); else if(node4.toElement().tagName() == "condition") qDebug() << " +condition:" << node4.toElement().attribute("data"); node4 = node4.nextSibling(); } }
- 結果
- "forecast_information" +city: "taipei" +postal_code: "taipei" +latitude_e6: "" +forecast_date: "" +current_date_time: "2010-09-29 23:00:00 +0000" +unit_system: "US" - "current_conditions" +condition: "Clear" +temp_f: "82" +temp_c: "28" +humidity: "" +icon: "/ig/images/weather/sunny.gif" +wind_condition: "Wind: mph" - "forecast_conditions" +day_of_week: "Thu" +low: "75" +high: "87" +icon: "/ig/images/weather/rain.gif" +condition: "Rain" - "forecast_conditions" +day_of_week: "Fri" +low: "77" +high: "89" +icon: "/ig/images/weather/cloudy.gif" +condition: "Cloudy" - "forecast_conditions" +day_of_week: "Sat" +low: "77" +high: "91" +icon: "/ig/images/weather/cloudy.gif" +condition: "Cloudy" - "forecast_conditions" +day_of_week: "Sun" +low: "73" +high: "86" +icon: "/ig/images/weather/rain.gif" +condition: "Rain"
-
【其它】
- accuweather.com 可和Google Weather 作比較
http://www.accuweather.com/zh-tw/tw/taipei-shih/taipei/quick-look.aspx
【參考】
- 天氣預報輕鬆看, Google Chrome : Weather Forecast & Google Weather
http://izaka.pixnet.net/blog/post/24856856 - 絕贊的iphone 天氣軟體-Accuweather
http://kevine.wordpress.com/2008/12/24/絕贊的iphone-天氣軟體-accuweather/ - DOM和SAX 比較
http://sls.weco.net/blog/lorrance/29-may-2008/9711 - What's XML DOM and SAX?
http://andypony.mis.stut.edu.tw/teach/xml_html/xmlteach2_4.htm - C GUI programming with Qt4
http://www.qteverywhere.com/qt/book/c-gui-programming-with-qt-4-2ndedition.pdf