Linux-基于网络爬虫技术的天气数据查询

一,获取报文数据

复制这个网址 去掉s

并且获取appkey和sign 再替换到到上图二的网址中,打开修改好的网址

这样子我们就可以用了

点击network 找到右下角的ip地址和端口

ip地址:103.205.5.206 端口:80

点击row完全展开,复制全部的报文去写字本(方便等会编辑好放进代码中)

二,要求

实现下图的功能

三,编程思路

1,模块图

项目是干嘛的

用 C 语言手动发 HTTP 请求,把服务器返回的 JSON 字符串里的天气数据抠出来打印。

整体流程:Socket 建连接 → 发 HTTP 请求 → 收 JSON 响应 → 手动解析字段 → 打印


一、网络连接怎么写(每次查询都要走这套)

cs 复制代码
// 1. 建套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);

// 2. 填服务器地址
struct sockaddr_in ser;
bzero(&ser, sizeof(ser));
ser.sin_family      = AF_INET;
ser.sin_port        = htons(80);                     // HTTP 端口 80
ser.sin_addr.s_addr = inet_addr("103.205.5.206");    // k780 服务器 IP

// 3. 连接(注意强转,typedef struct sockaddr* SA 是为了这里)
connect(sockfd, (SA)&ser, sizeof(ser));

// 4. 发请求 / 收响应
send(sockfd, buf, strlen(buf), 0);
bzero(buf, sizeof(buf));
recv(sockfd, buf, sizeof(buf), 0);

// 5. 用完关掉!(get_weather 忘写了这行,会泄漏 fd)
close(sockfd);

二、HTTP 请求怎么构造

请求本质就是一段有格式的纯文本,用 sprintf 把城市名拼进去:

复制代码
char buf[5000] = {0};
sprintf(buf,
    "GET /?app=weather.today&cityNm=%s&appkey=78675&sign=xxx&format=json HTTP/1.1\r\n"
    "Host: api.k780.com\r\n"
    "User-Agent: Mozilla/5.0\r\n"
    "Connection: keep-alive\r\n\r\n",   // 末尾必须有空行 \r\n\r\n
    city);                               // city 是全局变量,set_city() 里改

两个接口只有 app= 这个参数不一样:

  • 实时天气:app=weather.today
  • 生活指数:app=weather.lifeindex

三、JSON 字段怎么提取

服务器返回的是 JSON 字符串,不用任何库,纯靠字符串函数手动抠:

复制代码
// 假设 JSON 里有 "days":"2026-03-06"
char *begin = strstr(buf, "days");      // 找到 key
begin = begin + strlen("days") + 3;    // +3 是跳过 ":"  三个字符(结束引号+冒号+开始引号)
char *end = strchr(begin, '"');         // 找到 value 结束的引号
size_t len = end - begin;
memcpy(days, begin, len);
days[len] = '\0';

为什么 +3? key 后面固定是 ":" 三个字符,跳过后指针就落在 value 的第一个字符上。


四、生活指数的多日遍历

生活指数接口返回的是数组,有好几天的数据,要循环处理:

复制代码
{"result":[{第一天数据},{第二天数据},{第三天数据}]}

思路:遇到 { 记开始,遇到 } 就在这段范围内提取字段打印,遇到 ] 结束循环。

cs 复制代码
char *start = strstr(buf, "result");  // 从 result 字段开始扫
char *obj_start = NULL;

while (1) 
{
    if (*start == '{')      obj_start = start;   // 新对象开始
    else if (*start == '}') {                    // 当前对象结束,提取字段
        // strstr(obj_start, "days") ...
        // strstr(obj_start, "week_1") ...  ← 注意是 week_1 不是 week!
        printf(...);
    }
    if (*(start + 1) == ']') break;  // 数组结束
    start++;
}
close(sockfd);  // 这个函数记得关

五、两个接口字段名的区别(容易搞混)

字段 实时天气接口 生活指数接口
星期 week week_1
紫外线 ❌ 没有 lifeindex_uv_attr
洗车 ❌ 没有 lifeindex_xc_attr
穿衣 ❌ 没有 lifeindex_ct_attr

六、踩过的坑

原因 修复
typedef struct sockaddr *(SA) 编译报错 括号位置不对 改成 typedef struct sockaddr* SA
void 函数里 return 1 报错 void 不能返回值 改成 return;
生活指数 week 字段崩溃 字段是 week_1,用 week 找不到,strstr 返回 NULL 改用 week_1
weather 字段取出来是 weather_curr 的值 strstr("weather") 先匹配到 weather_curr 先提取 weather_curr,再提取 weather
strcmp(city, "\n") 默认城市逻辑没效果 scanf 不读换行符,这个判断永远假 删掉这段逻辑
查询多次后报 too many open files get_weather 没有 close(sockfd) 函数末尾加 close(sockfd)
相关推荐
大树883 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠3 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质3 小时前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush43 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5203 小时前
Linux 11 动态监控指令top
linux
小宇宙Zz4 小时前
Maven依赖冲突
java·服务器·maven
Inhand陈工4 小时前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智5 小时前
ARP代理--工作原理
运维·网络·arp·arp代理
不会C语言的男孩5 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
shushangyun_5 小时前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化