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)
相关推荐
雾岛听蓝21 小时前
C文件操作与系统IO
linux·c语言·开发语言·经验分享·笔记·算法
coderwei12321 小时前
Ubantu服务器构建openclaw并接入飞书
运维·服务器
开开心心就好1 天前
跨平台高速下载工具,支持浏览器功能强大
运维·服务器·windows·pdf·旅游·媒体·1024程序员节
心易行者1 天前
别再说“在我的机器上能跑”了!Docker 入门指南,专治各种环境不服
运维·人工智能·docker·容器
盐焗西兰花1 天前
鸿蒙学习实战之路-Share Kit系列(7/17)-自定义分享面板操作区
linux·学习·harmonyos
Keanu-1 天前
Redis 主从复制及哨兵模式配置
服务器·数据库·redis
Yupureki1 天前
《C++实战项目-高并发内存池》3.ThreadCache构造
服务器·c语言·c++·算法·哈希算法
zhim001 天前
【保姆级教程】使用 Docker 部署 PostgreSQL + pgvector(含踩坑指南)
linux·docker
开朗觉觉1 天前
将json字符串转换为json对象
linux·服务器·python
脱脱克克1 天前
OpenClaw 腾讯云 + 火山方舟(Volcengine Ark)完整安装与扩展教程
linux·腾讯云·openclaw