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)
相关推荐
satadriver14 小时前
ip-guard网络通信加解密
linux·网络·tcp/ip
meilindehuzi_a15 小时前
【Linux 进程基础】一文读懂命令行参数与环境变量
linux·服务器
燕-孑15 小时前
Nginx详解——进阶
运维·nginx
用户868592144187415 小时前
Linux I2C 调试实录:用寄存器打印揪出 TRISE 配置过小
linux
脆皮炸鸡75515 小时前
进程信号~信号的产生
linux·服务器·开发语言·经验分享·笔记·学习方法
Emtronix英创15 小时前
RK3568 CAN驱动测试及使用说明
linux·arm开发·rk3568·全国产主板
vortex515 小时前
CentOS 系包管理器完全指南:从 dnf 到 rpm
linux·运维·centos
小当家.10515 小时前
Codex + SSH 远程运维实战:让 AI 管你的云服务器
运维·服务器·人工智能·ssh·codex·ai-coding
SZ放sai哑滋15 小时前
工控机刷Linux、Qt教程
linux·运维·服务器
自由且自律15 小时前
ceph实战,基于docker部署
运维·ceph·docker·容器·云计算