天气预报爬虫
一、获取天气接口
主要通过nowapi注册用户之后,进入相应的接口,进行抓取报文。
二、wireshark抓取报文,解析cjson格式
Http的交互过程
1.建立TCP连接
2.发送HTTP请求报文
3.回复HTTP响应报文
4.断开TCP连接
CJSON的使用办法
1. JSON与cJSON
JSON —— 轻量级的数据格式
JSON 全称 JavaScript Object Notation,即 JS对象简谱,是一种轻量级的
数据格式。
它采用完全独立于编程语言的文本格式来存储和表示数据,语法简洁、层
次结构清晰,易于人阅读和编写,同时也易于机器解析和生成,有效的提
升了网络传输效率。
2、CJSON的语法
构清晰,易于人阅读和编写,同时也易于机器解析和生成,有效的提
升了网络传输效率。
JSON语法规则
- JSON对象是一个无序的"名称/值"键值对的集合:
- 以"{“开始,以”}"结束,允许嵌套使用;
- 每个名称和值成对出现,名称和值之间使用":"分隔;
- 键值对之间用","分隔
- 在这些字符前后允许存在无意义的空白符;
- 对于键值,可以有如下值:
- 一个新的json对象
- 数组:使用"[“和”]"表示
- 数字:直接表示,可以是整数,也可以是浮点数
- 字符串:使用引号"表示
- 字面值:false、null
3、CJOSN的解析
解析方法
解析JSON数据的过程,其实就是剥离一个一个链表节点(键值对)的过程。
解析方法如下:
① 创建链表头指针:
cJSON* cjson_test = NULL;
② 解析整段JSON数据,并将链表头结点地址返回,赋值给头指针:
解析整段数据使用的API只有一个:
(cJSON *) cJSON_Parse(const char *value);
③ 根据键值对的名称从链表中取出对应的值,返回该键值对(链
表节点)的地址
(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char *
const string);
④ 如果JSON数据的值是数组,使用下面的两个API提取数据:
(int) cJSON_GetArraySize(const cJSON *array);
(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
三、设计框架
3.2、设计思路
了解服务器断口的http请求的基本格式之后,充当客户端,对该服务器进行请求,服务器对发送的报文,进行回发,我们只需将从服务器爬虫下来的数据进行解析即可。
四、函数接口
4.1、命令接口
接口 | 参数 | 返回值 | 接口描述 |
void menu1(void) | 无 | 0 | 菜单函数 |
int clink(const char *ip,const char *port) | Ip和端口号 | fd | 建立连接 |
void recieve(char *choice,char *buf,int fd,char *p) | 选择的模式,城市,fd,堆空间 | 0 | 发送报文和接收服务器报文 |
void stime(char *p) | 堆空间 | 0 | 实时时间 |
void fweek(char *p) | 堆空间 | 0 | 未来世界 |
Break | 8 | 0 | 退出 |
4.2、查看对应城市的天气
接口名称 | 参数说明 | 返回值 | 接口描述 |
Scanf(“%s”,&a) | 传递指针数组的首地址 | 0 | 输入城市名 |
4.3、 查询实时天气
接口名称 | 参数说明 | 返回值 | 接口描述 |
void stime(char *p) | 堆空间的首地址 | 0 | 用来显示实时天气 |
4.4、查询未来天气
接口名称 | 参数说明 | 返回值 | 接口描述 |
voidfweek(char*p) | 传递管道文件描述符 | 0 | 用来给mpalyer发送停止信息 |
五、函数的封装与代码实现
5.1、主函数
/*************************************************************************
> File Name: main.c
> Author: yas
> Mail: rage_yas@hotmail.com
> Created Time: Sat 24 Aug 2024 05:01:26 PM
************************************************************************/
#include<stdio.h>
#include"menu.h"
#include"send.h"
#include<stdlib.h>
#include<string.h>
#include <unistd.h>
int main(int agrc,char *agrv[])
{
int a;
char city[10] = {0};
int ret;
char *p = (char *)malloc(1024*1024*3);
menu();
printf("输入城市名称:");
scanf("%s",city);
while(1)
{
menu1();
scanf("%d",&a);
if(a == 2)
{
char choice[] = "app=weather.today";
ret = clink("103.205.5.228","80");
recieve(choice,city,ret,p);
// seto(p,ret);
stime(p,ret);
}
else if(a == 3)
{
char choice[] = "app=weather.future";
ret = clink("103.205.5.228","80");
memset(p,0,3*1024*1024);
recieve(choice,city,ret,p);
//seto(q,ret);
fweek(p,ret);
}
else if(a == 4)
{
break;
}
}
free(p);
return 0;
}
5.2、菜单栏
#include<stdio.h>
void menu(void)
{
printf("+-----------------------+\n");
printf("|1.配置城市 |\n");
printf("|2.查看实时天气 |\n");
printf("|3.查看未来一周天气 |\n");
printf("|4.退出 |\n");
printf("| |\n");
printf("+-----------------------+\n");
}
5.3、发送报文
/*************************************************************************
> File Name: send.c
> Author: yas
> Mail: rage_yas@hotmail.com
> Created Time: Sun 25 Aug 2024 02:27:12 PM
************************************************************************/
#include<stdio.h>
#include<head.h>
#include<string.h>
#include<cJSON.h>
#include <unistd.h>
void menu1(void)
{
printf("----------选择模式--------------\n");
printf("2.查看实时天气 \n");
printf("3.查看未来天气 \n");
printf("4.退出 \n");
printf("-------------------------------\n");
}
int clink(const char *ip,const char *port)
{
int fd = socket(AF_INET,SOCK_STREAM,0);
if(fd < 0)
handle_error_ret("socket fail");
struct sockaddr_in seraddr;
memset(&seraddr,0,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr(ip);
seraddr.sin_port = htons(atoi(port));
if(connect(fd,(const struct sockaddr *)&seraddr,sizeof(seraddr)) < 0)
handle_error_ret("connect_server fail");
return fd;
}
void recieve(char *choice,char *buf,int fd,char *p)
{
char buf1[1024] = {0};
int i = 0;
sprintf(buf1,"GET /?%s&weaid=%s&appkey=73824&sign=800f3bbca4119c9624422f593f4caa36&format=json HTTP/1.1\r\n",choice,buf);
char * buf2[] = {"Host: api.k780.com\r\n","User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0\r\n","Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n","Accept-Language: en-US,en;q=0.5\r\n","Accept-Encoding: gzip, deflate\r\n","Connection: close\r\n","Upgrade-Insecure-Requests: 1\r\n\r\n",NULL};
write(fd,buf1,strlen(buf1));
while(buf2[i] != NULL)
{
write(fd,buf2[i],strlen(buf2[i]));
++i;
}
while(1)
{
char buf3[1024] = {0};
int ret =read(fd,buf3,sizeof(buf3)-1);
if(ret <= 0)
{
break;
}
strcat(p,buf3);
}
}
void stime(char *p,int fd)
{
char *q = index(p,'{');
cJSON* cjson_test = NULL;
cJSON* cjson_result = NULL;
cJSON* cjson_result_humidity = NULL;
cJSON* cjson_result_temp_high = NULL;
cJSON* cjson_result_temp_low = NULL;
cJSON* cjson_result_temperature_curr = NULL;
cJSON* cjson_result_humi_high = NULL;
cJSON* cjson_result_humi_low = NULL;
cJSON* cjson_result_weather_curr = NULL;
cJSON* cjson_result_wind = NULL;
cjson_test = cJSON_Parse(q);
if(cjson_test == NULL)
{
perror("parse fail");
}
cjson_result = cJSON_GetObjectItem(cjson_test,"result");
cjson_result_humidity = cJSON_GetObjectItem(cjson_result,"humidity");
cjson_result_temperature_curr = cJSON_GetObjectItem(cjson_result,"temperature_curr");
cjson_result_temp_high = cJSON_GetObjectItem(cjson_result,"temp_high");
cjson_result_temp_low = cJSON_GetObjectItem(cjson_result,"temp_low");
cjson_result_humi_high = cJSON_GetObjectItem(cjson_result,"humi_high");
cjson_result_humi_low = cJSON_GetObjectItem(cjson_result,"humi_low");
cjson_result_weather_curr = cJSON_GetObjectItem(cjson_result,"weather_curr");
cjson_result_wind = cJSON_GetObjectItem(cjson_result,"wind");
printf("湿度 %.0f\n",cjson_result_humidity->valuedouble);
printf("温度 %s\n",cjson_result_temperature_curr->valuestring);
printf("最高温度 %d\n",cjson_result_temp_high->valueint);
printf("最低温度 %d\n",cjson_result_temp_low->valueint);
printf("最高湿度 %d\n",cjson_result_humi_high->valueint);
printf("最低湿度 %d\n",cjson_result_humi_low->valueint);
printf("天气 %s\n",cjson_result_weather_curr->valuestring);
printf("风力 %s\n",cjson_result_wind->valuestring);
cJSON_Delete(cjson_test);
close(fd);
}
void fweek(char *p,int fd)
{
cJSON* cjson_test = NULL;
cJSON* cjson_result = NULL;
char *q = index(p,'{');
//printf("-----------------------\n%s----------------\n",q);
cjson_test = cJSON_Parse(q);
if(cjson_test == NULL)
{
printf("-------");
perror("parsier error");
}
cjson_result = cJSON_GetObjectItem(cjson_test,"result");
if(cjson_result == NULL)
{
perror("result");
}
int Arrlen = cJSON_GetArraySize(cjson_result);
for(int i = 0;i < Arrlen;++i)
{
cJSON* SubObj = cJSON_GetArrayItem(cjson_result,i);
if(NULL == SubObj)
{
perror("erro");
continue;
}
if(cJSON_GetObjectItem(SubObj,"weaid") == NULL)
{
perror("fai;");
return ;
}
if(cJSON_GetObjectItem(SubObj,"week") == NULL)
{
perror("fail1");
return;
// printf("星期 %s\n", cJSON_GetObjectItem(SubObj,"week")->valuestring);
}
if(cJSON_GetObjectItem(SubObj,"temperature") == NULL)
{
perror("fail1");
return ;
//printf("温度 %s\n", cJSON_GetObjectItem(SubObj,"temperature")->valuestring);
}
if(cJSON_GetObjectItem(SubObj,"humidity") == NULL)
{
perror("fail1");
return;
//printf("湿度 %.0f\n", cJSON_GetObjectItem(SubObj,"humidity")->valuedouble);
}
if(cJSON_GetObjectItem(SubObj,"temp_high") == NULL)
{
perror("faili2");
return;
//printf("星期 %d\n", cJSON_GetObjectItem(SubObj,"temp_high")->valueint);
}
if(cJSON_GetObjectItem(SubObj,"temp_low") == NULL)
{
perror("fail3");
return;
// printf("星期 %d\n", cJSON_GetObjectItem(SubObj,"temp_low")->valueint);
}
if(cJSON_GetObjectItem(SubObj,"humi_high") == NULL)
{
perror("fail4");
return;
// printf("星期 %d\n", cJSON_GetObjectItem(SubObj,"humi_high")->valueint);
}
if(cJSON_GetObjectItem(SubObj,"humi_low") == NULL)
{
perror("fail5");
return ;
//printf("星期 %d\n", cJSON_GetObjectItem(SubObj,"humi_low")->valueint);
}
if(cJSON_GetObjectItem(SubObj,"weather") == NULL)
{
perror("fail6");
return ;
// printf("星期 %s\n", cJSON_GetObjectItem(SubObj,"weather")->valuestring);
}
if(cJSON_GetObjectItem(SubObj,"wind") == NULL)
{
perror("fail7");
return;
//printf("星期 %s\n", cJSON_GetObjectItem(SubObj,"wind")->valuestring);
}
printf("星期 %s\n温度 %s\n湿度%.0f\n最高温度%d\n最低温度%d\n最高湿度%d\n最低湿度%d\n天气%s\n风力%s\n",
cJSON_GetObjectItem(SubObj,"week")->valuestring,cJSON_GetObjectItem(SubObj,"temperature")->valuestring,cJSON_GetObjectItem(SubObj,"humidity")->valuedouble,cJSON_GetObjectItem(SubObj,"temp_high")->valueint,cJSON_GetObjectItem(SubObj,"temp_low")->valueint,cJSON_GetObjectItem(SubObj,"humi_high")->valueint,cJSON_GetObjectItem(SubObj,"humi_low")->valueint,cJSON_GetObjectItem(SubObj,"weather")->valuestring,cJSON_GetObjectItem(SubObj,"wind")->valuestring);
}
// cJSON_Delete(cjson_test);
close(fd);
}
六、实现效果展示