Linux下通过curl实现新浪天气API应用

编程入门 行业动态 更新时间:2024-10-16 02:28:43

Linux下通过curl实现<a href=https://www.elefans.com/category/jswz/34/1766670.html style=新浪天气API应用"/>

Linux下通过curl实现新浪天气API应用

Linux下通过curl实现新浪天气API应用

新浪天气API的使用方法:

API地址:.php?city=%B1%B1%BE%A9&password=DJOYnieT8234jlsK&day=0

红色标记为城市代码(也就是城市的中文转为GB2312的十六进制代码,比如北京对应的GB2312十六进制代码为B1B1BEA9),实际上需要查哪个城市就把红色标记改为对应城市代码即可.而实际上打开此url后对应的是一个xml文件,里面包括了此城市的天气信息.

<?xml version="1.0" encoding="UTF-8"?>
<!-- published at 2014-10-31 17:08:03 -->
<Profiles>
<Weather>
<city>北京</city>
<status1>小雨</status1>
<status2>多云</status2>
<figure1>xiaoyu</figure1>
<figure2>duoyun</figure2>
<direction1>无持续风向</direction1>
<direction2>无持续风向</direction2>
<power1>≤3</power1>
<power2>≤3</power2>
<temperature1>14</temperature1>
<temperature2>9</temperature2>
<ssd>5</ssd>
<tgd1>16</tgd1>
<tgd2>16</tgd2>
<zwx>2</zwx>
<ktk>6</ktk>
<pollution>3</pollution>
<xcz></xcz>
<zho></zho>
<diy></diy>
<fas></fas>
<chy>4</chy>
<zho_shuoming>暂无</zho_shuoming>
<diy_shuoming>暂无</diy_shuoming>
<fas_shuoming>暂无</fas_shuoming>
<chy_shuoming>套装、夹衣、风衣、夹克衫、西服套装、马甲衬衫配长裤</chy_shuoming>
<pollution_l>轻度</pollution_l>
<zwx_l>弱</zwx_l>
<ssd_l>略凉</ssd_l>
<fas_l>暂无</fas_l>
<zho_l>暂无</zho_l>
<chy_l>夹衣类</chy_l>
<ktk_l>适宜开启(制热)</ktk_l>
<xcz_l>暂无</xcz_l>
<diy_l>暂无</diy_l>
<pollution_s>对空气污染物扩散无明显影响</pollution_s>
<zwx_s>紫外线弱</zwx_s>
<ssd_s>感觉有些凉,但是凉意微薄,不影响户外活动的开展。</ssd_s>
<ktk_s>适宜开启空调</ktk_s>
<xcz_s>暂无</xcz_s>
<gm>2</gm>
<gm_l>易发期</gm_l>
<gm_s>天气很凉,季节转换的气候,慎重增加衣服;较易引起感冒;</gm_s>
<yd>5</yd>
<yd_l>不适宜</yd_l>
<yd_s>虽然晴空万里,但是天气较凉,多数人不适宜户外运动;</yd_s>
<savedate_weather>2014-10-31</savedate_weather>
<savedate_life>2014-10-31</savedate_life>
<savedate_zhishu>2014-10-31</savedate_zhishu>
</Weather>
</Profiles>

现在我们的工作就是使用curl打开这个xml文件并且将其转换为我们需要的数据结构.

#ifndef __SINA_WEATHER__
#define __SINA_WEATHER__#include <stdio.h>#define FALSE (0)
#define TRUE (!0)#define SINA_WEATHER_URL_HEAD ".php?city="
#define SINA_WEATHER_URL_TAIL "&password=DJOYnieT8234jlsK&day=0"struct date {short year;short month;short day;
};struct weather_info {char * city;//天气情况(中文)char * status1;char * status2;//天气情况(拼音)char * figure1;char * figure2;//风向char * direction1;char * direction2;//风级char * power1;char * power2;//温度int temperature1;int temperature2;//体感指数数值int ssd;//体感度指数char * ssd_l;//体感度指数说明char * ssd_s;//体感温度int tgd1;int tgd2;//紫外线指数数值int zwx;//紫外线指数char * zwx_l;//紫外线指数说明char * zwx_s;//空调指数数值int ktk;//空调指数char * ktk_l;//空调指数说明char * ktk_s;//污染指数数值int pollution;//污染扩散条件char * pollution_l;//污染指数说明char * pollution_s;//穿衣指数数值int chy;//穿衣指数char * chy_l;//穿衣说明char * chy_shuoming;//洗车指数数值int xcz;//洗车指数char * xcz_l;//洗车指数说明char * xcz_s;//感冒指数数值int gm;//感冒指数char * gm_l;//感冒指数说明char * gm_s;//运动指数数值int yd;//运动指数char * yd_l;//运动指数说明char * yd_s;struct date weather_date;struct date life_date;struct date zhishu_date;
};struct weather_info * get_weather_info_from_sina (const char * city_name);#endif

先说一下流程,首先设计想法是就定义一个接口,调用时只需要输入一个城市名称,则自动返回此城市的天气信息结构体,而在内部,分别执行了UTF-8转GB2312格式, curl初始化, 获取天气XML信息, 填充struct weather_info结构体.

流程图:

代码(sina_weather.c):

#include <stdio.h>
#include <curl/curl.h>
#include <iconv.h>#include "sina_weather.h"
//根据key获取xml中对应的值
char * get_xml_key_value (const char * xml, char * key)
{char * head;char * tail;char stamp[1024];char * value;sprintf(stamp, "<%s>", key);if ((head = strstr (xml, stamp)) == NULL)return NULL;head = head + strlen (stamp);while (isspace (head[0]))head ++;sprintf(stamp, "</%s>", key);if ((tail = strstr (head, stamp)) == NULL)return NULL;while (isspace(tail[-1]) && (tail > head))tail --;if (tail > head){value = calloc (tail - head + 1, 1);memcpy (value, head, tail - head);value[tail - head] = 0x00;}return value;
}
//UTF-8转GB2312
int utf8_to_gb2312 (const char * src, char * dest_buf)
{iconv_t con;int src_length = strlen (src);if( (con = iconv_open ("gb2312", "utf-8")) ==0 )return FALSE;memset (dest_buf, 0, src_length);if(-1 == iconv (con, &src, &src_length, &dest_buf, &src_length))return FALSE;iconv_close (con);return TRUE;
}
//将一个GB2312字符串转换为它的十六进制字符串(每个字符用%隔开)
char * str_convert_to_gb2312_hex (const char * src)
{if (src == NULL)return NULL;int length = strlen (src) - 2;int index = 0;int num = 0;char * gb_str = calloc (((length) + 1), 1);char * hex_str = calloc ((length * 3) + 1, 1);utf8_to_gb2312 (src, gb_str);while ((index / 3) < length) {hex_str[index] = '%';sprintf (&hex_str[index + 1], "%02X", gb_str[index / 3] & 0xff);index = index + 3;}hex_str[length * 3] = '\0';return hex_str;
}void convert_to_gb2312_clean (char * str)
{free (str);
}
//curl下载时的回调函数,当下载到数据时会调用此函数进行操作
size_t down_data_callback (void * ptr, size_t size, size_t nmemb, void * user_buf)
{strcat (user_buf, ptr);return size * nmemb;
}uint64_t curl_get_content (const char * url, char * content)
{if ((url == NULL) || (content == NULL))return;CURL * curl = curl_easy_init ();curl_easy_setopt (curl, CURLOPT_URL, url);                               //设置curl的目标url地址curl_easy_setopt (curl, CURLOPT_TIMEOUT, 15);                            //下载超时时间curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);                            //屏蔽其他信号curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, down_data_callback);      //设置下载回调函数curl_easy_setopt (curl, CURLOPT_WRITEDATA, content);                     //设置下载数据保存缓冲区(此参数会传到down_data_callback的user_buf)CURLcode retval = curl_easy_perform (curl);if (retval == CURLE_OK) {double down_length = 0;curl_easy_getinfo (curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &down_length);curl_easy_cleanup (curl);return (uint64_t)down_length;}curl_easy_cleanup (curl);return 0;
}struct weather_info * weather_info_get_from_xml (const char * xml, struct weather_info * w_info)
{if ((xml == NULL) || (w_info == NULL))return w_info;char * str_data = NULL;w_info->city = get_xml_key_value (xml, "city");w_info->status1 = get_xml_key_value (xml, "status1");w_info->status1 = get_xml_key_value (xml, "status1");str_data = get_xml_key_value (xml, "temperature1");w_info->temperature1 = (int) atoi (str_data);free (str_data);str_data = get_xml_key_value (xml, "temperature2");w_info->temperature2 = (int) atoi (str_data);free (str_data);  //此处省略N多,基本都同上操作.
}struct weather_info * get_weather_info_from_sina (const char * city_name)
{if (city_name == NULL)return NULL;CURL * curl = NULL;CURLcode retval = 0;char xml_data[4096];char url[1024] = SINA_WEATHER_URL_HEAD;char * city_hex = str_convert_to_gb2312_hex (city_name);struct weather_info * sina_w_info = calloc (sizeof (struct weather_info), 1);strcat (url, city_hex);strcat (url, SINA_WEATHER_URL_TAIL);convert_to_gb2312_clean (city_hex);uint64_t down_size = curl_get_content (url, xml_data);if (down_size == 0) {free (sina_w_info);return NULL;}weather_info_get_from_xml (xml_data, sina_w_info);return sina_w_info;
}

CURL:

或许有些同学不太清楚怎么在c中使用curl库,其实使用的方法很简单,就简单说明一下,在ubuntu下安装curl库命令

apt-get install libcurl-nss-dev

在编译时需要加入的选项:

-lcurl
  使用curl下载时常规的代码顺序为:

CURL * curl = curl_easy_init ();                       //初始化curl_easy_setopt (curl, CURLOPT_URL, url);             //具体设置代表的意思在.htmlcurl_easy_setopt (curl, CURLOPT_TIMEOUT, 15);curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, down_data_callback);curl_easy_setopt (curl, CURLOPT_WRITEDATA, content);CURLcode retval = curl_easy_perform (curl);           //执行操作if (retval == CURLE_OK) {   //添加所需要处理的代码       ........}curl_easy_cleanup (curl);                             //清空

在使用curl下载时,会设置CURLOPT_WRITEFUNCTION,此设置主要是为了在下载有数据过来时,调用down_data_callback这个回调函数,并将数据保存到content这个缓冲区中.

curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, down_data_callback);
curl_easy_setopt (curl, CURLOPT_WRITEDATA, content);size_t down_data_callback (void * ptr, size_t size, size_t nmemb, void * user_buf)
{strcat (user_buf, ptr);return size * nmemb;
}

更多推荐

Linux下通过curl实现新浪天气API应用

本文发布于:2024-02-06 20:37:50,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1751395.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:新浪   天气   Linux   curl   API

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!