一、获取天气数据
准备工作
一、点击阿里云链接阿里云,搜索易源天气,找到下方的购买调试入口:(其他天气也可以,请求参数可能有不同)
2、登录后点击购买,新用户不用花钱,但是只能访问100次。
三、购买后找到购买界面下面有一个调试,或者到自己的管理控制台找到已购买的API:
四、进入调试界面,输入区域名字,点击发送请求,可以接收到返回信息,说明调试成功,记录下图红圈中的重要参数,要写到代码。
五、下载cJOSN:cJOSN下载链接
这是我下载好的cJOSN源码,本教程只需要用到cJOSN.c与cJOSN.h
到这准备工作就做完了。
相关知识点
HTTP请求报文格式(注意空格与换行符):
GET /spot-to-weather?area=广州 HTTP/1.1\r\n
Host: weather01.market.alicloudapi.com\r\n
Authorization:APPCODE xxxxxxxxxxx
C语言请求数据代码例程:
//获取请求数据
//Authorization需要到网上自己购买
char *httpRequest(const char *host)
{
static char request[1024];
snprintf(request, 1024, "GET /spot-to-weather?area=广州 HTTP/1.1\r\n"
"Host: weather01.market.alicloudapi.com\r\n"
"Authorization: APPCODE xxxxxxxx\r\n"
"\r\n", host);
return request;
}
HTTP响应报文格式
发送请求后http会返回数据,格式如下:
http返回的数据:
数据头
HTTP/1.1 200 OK Date: Thu, 10 Sep 2020 07:06:10 GMT Content-Type:
application/json;charset=utf-8 Content-Length: 2708 Connection:
keep-alive Keep-Alive: timeout=25 Vary: Accept-Encoding
Access-Control-Allow-Headers: * Server: openresty showapi_fee_num: 1
X-Ca-Request-Id: 24BBCE93-5192-4A51-8522-8EFFBDE6C5B1
Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Max-Age: 1728000
数据本文(josn格式)
{
“showapi_res_error”: “”,
“showapi_res_id”: “5f59d0628d57ba481d3fa586”,
“showapi_res_code”: 0,
“showapi_res_body”: {“time”:“20200910120000”,“ret_code”:0,“now”:{“weather_code”:“01”,“aqiDetail”:{“co”:“0.6”,“num”:“231”,“so2”:“11”,“area”:“广州”,“o3”:“104”,“no2”:“25”,“aqi”:“44”,“quality”:“优质”,“pm10”:“44”,“pm2_5”:“25”,“o3_8h”:“91”,“primary_pollutant”:“O3”},“wind_direction”:“西南风”,“temperature_time”:“15:00”,“wind_power”:“1级”,“aqi”:“44”,“sd”:“59%”,“weather_pic”:“http://app1.showapi.com/weather/icon/day/01.png”,“weather”:“多云”,“temperature”:“33”},“cityInfo”:{“c6”:“guangdong”,“c5”:“广州”,“c4”:“guangzhou”,“c3”:“越秀”,“c9”:“中国”,“c8”:“china”,“c7”:“广东”,“c17”:“+8”,“c16”:“AZ9200”,“c1”:“101280107”,“c2”:“yuexiu”,“c0”:“440104”,“longitude”:113.261,“c11”:“020”,“c10”:“3”,“latitude”:23.131,“c12”:“510000”,“c15”:“28”},“showapi_fee_code”:-1,“f1”:{“night_weather_code”:“04”,“day_weather”:“雷阵雨”,“night_weather”:“雷阵雨”,“jiangshui”:“85%”,“air_press”:“1007
hPa”,“night_wind_power”:“0-3级 <5.4m/s”,“day_wind_power”:“0-3级
<5.4m/s”,“day_weather_code”:“04”,“sun_begin_end”:“06:11|18:36”,“ziwaixian”:“最弱”,“day_weather_pic”:“http://app1.showapi.com/weather/icon/day/04.png”,“weekday”:4,“night_air_temperature”:“26”,“day_wind_direction”:“无持续风向”,“day_air_temperature”:“33”,“night_wind_direction”:“无持续风向”,“night_weather_pic”:“http://app1.showapi.com/weather/icon/night/04.png”,“day”:“20200910”},“f3”:{“night_weather_code”:“04”,“day_weather”:“中雨”,“night_weather”:“雷阵雨”,“jiangshui”:“84%”,“air_press”:“1007
hPa”,“night_wind_power”:“0-3级 <5.4m/s”,“day_wind_power”:“0-3级
<5.4m/s”,“day_weather_code”:“08”,“sun_begin_end”:“06:12|18:34”,“ziwaixian”:“最弱”,“day_weather_pic”:“http://app1.showapi.com/weather/icon/day/08.png”,“weekday”:6,“night_air_temperature”:“25”,“day_wind_direction”:“无持续风向”,“day_air_temperature”:“30”,“night_wind_direction”:“无持续风向”,“night_weather_pic”:“http://app1.showapi.com/weather/icon/night/04.png”,“day”:“20200912”},“f2”:{“night_weather_code”:“09”,“day_weather”:“雷阵雨”,“night_weather”:“大雨”,“jiangshui”:“82%”,“air_press”:“1007
hPa”,“night_wind_power”:“0-3级 <5.4m/s”,“day_wind_power”:“0-3级
<5.4m/s”,“day_weather_code”:“04”,“sun_begin_end”:“06:11|18:35”,“ziwaixian”:“最弱”,“day_weather_pic”:“http://app1.showapi.com/weather/icon/day/04.png”,“weekday”:5,“night_air_temperature”:“25”,“day_air_temperature”:“33”,“day_wind_direction”:“无持续风向”,“day”:“20200911”,“night_weather_pic”:“http://app1.showapi.com/weather/icon/night/09.png”,“night_wind_direction”:“无持续风向”}}
}
而有用的数据就是除了头部分的文本数据,这些数据是一个大数组,想要提取其中的某些数据显然有些困难。于是利用刚刚下载好的cJOSN 源码,利用其中的函数来解析这一堆杂乱的数据。
代码工程建立
一、把cJOSN.c与cJOSN.h 、你的主程序 拷贝到ubuntu 目录下:
二、编写代码(注意xxxxxxxx需要使用自己购买的APPCODE 编码,在调试信息可以看到)
/*************************************
* 数据来源:阿里云-易源天气
* 获取天气的网址:weather01.market.alicloudapi.com
****************************************/
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "cJSON.h"
#define SERV_PORT 80
//出错
void sys_err(const char *str)
{
perror(str);
exit(1);
}
//获取请求数据
//Authorization需要到网上自己购买,首次不收费 0.01元连接100次
char *httpRequest(const char *host)
{
static char request[1024];
snprintf(request, 1024, "GET /spot-to-weather?area=广州 HTTP/1.1\r\n"
"Host: %s\r\n"
"Authorization: APPCODE xxxxxxxx\r\n"
"\r\n", host);
return request;
}
int main(int argc, const char **argv)
{
if(argc != 2)
{
printf("input error: try ‘./client weather01.market.alicloudapi.com’\n");
exit(0);
}
cJSON *js=NULL;//JOSN解析结构体
cJSON *item=NULL;
cJSON *wer_item=NULL;
int lfd,cfd; //套接字
char buf[100*1024],j_buf[1024*100];//接收数组
struct hostent *ht = gethostbyname(argv[1]);//根据域名获得IP
if(ht == NULL){
perror("gethostbyname");
exit(0);
}
sprintf(buf,"%s", inet_ntoa(*((struct in_addr *)(ht->h_addr_list)[0])));
printf("解析IP:%s\n",buf);
struct sockaddr_in serv_addr; //服务器地址结构
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
//inet_pton(AF_INET, buf, &serv_addr.sin_addr); //两种方法赋值
serv_addr.sin_addr = *((struct in_addr *)(ht->h_addr_list[0]));
lfd = socket(AF_INET, SOCK_STREAM, 0);//新建网络套接字
if (lfd == -1)
sys_err("socket error");
printf("尝试连接...\n");//尝试连接网络地址
int ret = connect(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (ret != 0)
sys_err("connect err");
printf("已连接到:%s\n",argv[1]);
char *s = httpRequest(argv[1]);//获取请求数组
printf("发送请求:%s\n",s);
write(lfd,s,strlen(s)); //发送请求
read(lfd,buf,sizeof(buf));//获取数据
//printf("收到报文:%s\n",buf);
/***砍去头部,不然解析会出错****/
int j=0,flag=0;
for(int i=0; i<strlen(buf)+1; i++)
{
if(buf[i] == '{' || flag == 1){
flag = 1;
j_buf[j] = buf[i];
j++;
}
}//printf("砍头后的数据:%s\n",j_buf);
//printf("解析JOSN数据..\n");
js = cJSON_Parse(j_buf); //把去头的报文JOSN进行解析
//printf("%s\n",cJSON_Print(js));//打印解析好的报文数据
/*获取指定数据 层层查找法,要查看JOSN结构名称*/
//printf("指定数据获取:\n\n");
item = cJSON_GetObjectItem(js, "showapi_res_body");
printf("时间:%s\n",cJSON_GetObjectItem(item, "time")->valuestring);
item = cJSON_GetObjectItem(item, "now");
wer_item = cJSON_GetObjectItem(item, "aqiDetail");
//地名查看
wer_item = cJSON_GetObjectItem(wer_item, "area");
if(wer_item != NULL){
printf("地区:%s\n",wer_item->valuestring);
}
//天气查看
wer_item = cJSON_GetObjectItem(item, "weather");
if(wer_item != NULL){
printf("天气:%s\n",wer_item->valuestring);
}
//温度查看
wer_item = cJSON_GetObjectItem(item, "temperature");
if(wer_item != NULL){
printf("温度: %s℃\n",wer_item->valuestring);
}
//风向查看
wer_item = cJSON_GetObjectItem(item, "wind_direction");
if(wer_item != NULL){
printf("风向:%s\n",wer_item->valuestring);
}
//将json结构占用的数据空间释放
cJSON_Delete(js);
//关闭连接
close(lfd);
return 0;
}
三、编译:
#gcc cJSON.c client.c -o client
四、运行:
运行结果:
time:20200911180000
area:广州
weather:阴
temperature: 29℃
wind_direction:东风
取消代码中的打印注释可以看到详细返回,解析数据:
二、获取物流信息
根据获取天气同样操作可以获取物流信息
我用的是这个:
获取物流信息代码:
/*************************************
* 数据来源:阿里云-全国快递单号查询
* 获取物流的网址:jisukdcx.market.alicloudapi.com
****************************************/
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "cJSON.h"
#define SERV_PORT 80
#define INET "jisukdcx.market.alicloudapi.com"
//出错
void sys_err(const char *str)
{
perror(str);
exit(1);
}
//获取请求数据
//Authorization需要到网上自己购买
char *httpRequest(const char *number,const char *type,const char *host)
{
static char request[1024];
snprintf(request, 1024, "GET /express/query?" //路径
"number=%s&" //参数
"type=%s "
"HTTP/1.1\r\n"
"Host: %s\r\n"
"Authorization:APPCODE XXXXXXXXX\r\n"
"\r\n",number, type, host);
return request;
}
int main(int argc, const char **argv)
{
if(argc != 3)
{
printf("input error: try ‘./client 9899980059901 EMS’\n");
exit(0);
}
cJSON *js=NULL;//JOSN解析结构体
cJSON *item=NULL;
cJSON *wer_item=NULL;
int lfd,cfd; //套接字
char buf[100*1024],j_buf[1024*100];//接收数组
struct hostent *ht = gethostbyname(INET);//根据域名获得IP
if(ht == NULL){
perror("gethostbyname");
exit(0);
}
sprintf(buf,"%s", inet_ntoa(*((struct in_addr *)(ht->h_addr_list)[0])));
printf("解析IP:%s\n",buf);
struct sockaddr_in serv_addr; //服务器地址结构
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
//inet_pton(AF_INET, buf, &serv_addr.sin_addr); //两种方法赋值
serv_addr.sin_addr = *((struct in_addr *)(ht->h_addr_list[0]));
lfd = socket(AF_INET, SOCK_STREAM, 0);//新建网络套接字
if (lfd == -1)
sys_err("socket error");
printf("尝试连接...\n");//尝试连接网络地址
int ret = connect(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (ret != 0)
sys_err("connect err");
printf("已连接到:%s\n",INET);
char *s = httpRequest(argv[1],argv[2],INET);//获取请求数组
printf("发送请求:%s\n",s);
write(lfd,s,strlen(s)); //发送请求
usleep(1000);//等一会让数据发送完
read(lfd,buf,sizeof(buf));//获取数据
//printf("收到报文:%s\n",buf);
/***砍去头部,不然解析会出错****/
int j=0,flag=0;
for(int i=0; i<strlen(buf)+1; i++)
{
if(buf[i] == '{' || flag == 1){
flag = 1;
j_buf[j] = buf[i];
j++;
}
}//printf("砍头后的数据:%s\n",j_buf);
//printf("解析JOSN数据..\n");
js = cJSON_Parse(j_buf); //把去头的报文JOSN进行解析
//printf("%s\n",cJSON_Print(js));//打印解析好的报文数据
/*获取指定数据 层层查找法,要查看JOSN结构名称*/
printf("快递物流信息:\n\n");
item = cJSON_GetObjectItem(js, "result");
item = cJSON_GetObjectItem(item, "list");
bzero(buf,sizeof(buf));
sprintf(buf,"%s",cJSON_Print(item));
for(j=0; j<strlen(buf); j++){//除去字符串中不好看的字符
if(buf[j]=='{' || buf[j]=='}' || buf[j]=='"'
|| buf[j]==',' || buf[j]=='[' || buf[j]==']')
buf[j] = ' ';
}
printf("%s\n",buf);
//将json结构占用的数据空间释放
cJSON_Delete(js);
//关闭连接
close(lfd);
return 0;
}
编译运行: