之前有需要要做一个天气预报查询的程序,在网上也找了很多别人的程序试了试,发现很多都不怎么好使。
最近研究了一下,发现也不是很难。首先,必须找到一个好一点的接口。在网上搜索发现,国家气象局提供的接口好像还不错。
可以参考这片文章,对这个接口的介绍还蛮全面的:http://www.weste.net/2012/8-23/84850.html
通过接口,我们试试打开武汉的链接,可以看到以下数据:
{"weatherinfo":{"city":"武汉","cityid":"101200101","temp":"23","WD":"东风","WS":"2级","SD":"52%","WSE":"2","time":"15:20","isRadar":"1","Radar":"JC_RADAR_AZ9270_JB"}}
可以发现他采用的是Json格式保存的信息。
这里我尝试用两种方法来进行处理。
1.自己来解析这些数据,这里我试了解析实时的简单的天气信息。效果如下:
首先,我们需要定义一个地址的查询接口URL:
以武汉为例,我们可以实时查询其信息,在update函数中实现如下:
void testApp::update(){
if(ofGetElapsedTimef() - timeMark > 600.0f){ //每10分钟更新一次数据
string url = "http://www.weather.com.cn/data/sk/101200101.html"; //武汉天气的接口地址
ofHttpResponse response = ofLoadURL(url);
if(response.status == 200) {
char* pBuffer = response.data.getBinaryBuffer(); //得到相关的天气信息保存到char*中
wchar_t wPathname[512] = {0};
int len = MultiByteToWideChar(CP_UTF8, NULL, pBuffer, -1, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, pBuffer, -1, wPathname, len); //转换成wchar_t*
if(wcscmp(wPathname, weatherInfo) != 0){
memset(weatherInfo, 0, 512);
memcpy(weatherInfo, wPathname, 512);
if(wcscmp(weatherInfo, wPathname) == 0) {
wcout<<L"天气信息更新!\n"; //信息有变化,进行解析
infoVec = splitWstring(weatherInfo);
// string city, temp, WD, WS, SD, time;
city = getInfo(L"city");
temp = getInfo(L"temp");
SD = getInfo(L"SD");
wstring WD = getInfo(L"WD");
wstring WS = getInfo(L"WS");
time = getInfo(L"time");
wind = wcscat(const_cast<wchar_t*>(WD.c_str()), WS.c_str());
}
}else{
wcout<<L"天气信息无变化!\n";
}
}
timeMark = ofGetElapsedTimef();
}
}
这里根据得到数据的格式,写的解析函数splitWstring,得到保存有数据的vector:
vector<wstring> testApp::splitWstring(wstring s){ //解析字符串,把数据存入vector
wstring::size_type pos = 0, pre_pos = 0;
wstring tmpWstring;
vector<wstring> tmpVec;
while( (pre_pos = s.find_first_of(L'\"', pre_pos)) != wstring::npos ){
if( (pos = s.find_first_of(L'\"', pre_pos+1)) == wstring::npos ){
break;
}
tmpWstring = s.substr(pre_pos+1, pos-pre_pos-1);
tmpVec.push_back(tmpWstring);
pre_pos = pos+1;
}
return tmpVec;
}
<pre code_snippet_id="197469" snippet_file_name="blog_20140221_4_7379237" name="code" class="cpp">//得到相应的信息
wstring testApp::getInfo(const wstring index){
//由于相关的信息在key的下一个存储,所以直接取出来即可
for(vector<wstring>::iterator iter = infoVec.begin(); iter != infoVec.end() - 1; iter++) {
if(wcscmp(index.c_str(), (*iter).c_str()) == 0) {
return *(iter+1);
}
}
return NULL;
}
最后,在得到数据后,我们直接画出来就OK了:
void testApp::draw(){
bgImg.draw(0, 0, 240, 400);
if(city.size() != 0) {
//地点
font_ado.drawString(city, 80, 300);
//显示实时温度
font.drawString(temp, 25, 150);
font.drawString(L"℃", 105, 150);
//显示风向,风力
font_wind.drawString(wind, 30, 70);
//显示湿度
font_wind.drawString(L"湿度", 30, 85);
font_wind.drawString(SD, 60, 85);
//更新时间
font_time.drawString(L"更新时间", 160, 390);
font_time.drawString(time, 200, 390);
}
}
wstring testApp::getInfo(const wstring index){
//由于相关的信息在key的下一个存储,所以直接取出来即可
for(vector<wstring>::iterator iter = infoVec.begin(); iter != infoVec.end() - 1; iter++) {
if(wcscmp(index.c_str(), (*iter).c_str()) == 0) {
return *(iter+1);
}
}
return NULL;
}
2.第二种方法,解析我用的别人封装好的Json解析方法。
就是这位大神的作品:https://github.com/jefftimesten/ofxJSON
OK,走起,先把它加到of中。
通过Json我们能容易的得到相关信息,如下:
string url_ = "http://m.weather.com.cn/data/101200101.html";
bool parsingSuccessful = dateJson.open(url_);<span style="white-space:pre"> </span>//Json解析
if(parsingSuccessful) {
date = dateJson["weatherinfo"]["date"].asString();<span style="white-space:pre"> </span>//得到相关信息
date_y = dateJson["weatherinfo"]["date_y"].asString();
week = dateJson["weatherinfo"]["week"].asString();
index = dateJson["weatherinfo"]["index"].asString();
index_d = dateJson["weatherinfo"]["index_d"].asString();
index_uv = dateJson["weatherinfo"]["index_uv"].asString();
index_xc = dateJson["weatherinfo"]["index_xc"].asString();
index_tr = dateJson["weatherinfo"]["index_tr"].asString();
index_cl = dateJson["weatherinfo"]["index_cl"].asString();
index_ls = dateJson["weatherinfo"]["index_ls"].asString();
index_ag = dateJson["weatherinfo"]["index_ag"].asString();
for(int i=1; i<=6; i++){
string a, b, c;
a = "temp" + ofToString(i);
b = "weather" + ofToString(i);
c = "wind" + ofToString(i);
temps[i-1] = dateJson["weatherinfo"][a].asString();
weatheres[i-1] = dateJson["weatherinfo"][b].asString();
winds[i-1] = dateJson["weatherinfo"][c].asString();
}
}
最后把string转成wstring,我们就能正确的去显示中文的信息了:
//设置区域
std::wcout.imbue(std::locale("CHS"));
wchar_t* testApp::stringToWstring(string src) { //string转wstring
int len = src.size();
int wcslen = ::MultiByteToWideChar(CP_UTF8, NULL, src.c_str(), len, NULL, 0);
wchar_t* wszString = new wchar_t[wcslen + 1];
::MultiByteToWideChar(CP_UTF8, NULL, src.c_str(), len, wszString, wcslen);
wszString[wcslen] = L'\0';
return wszString;
}
最后还是一样,我们依次将它们画出来!效果如下,凑合看吧。
春雨惊春清谷天,
夏满芒夏暑相连。
秋处露秋寒霜降,
冬雪雪冬小大寒
。
上半年是六廿一,
下半年是八廿三。
每月两节日期定,
最多只差一两天。