一、导入库与全局配置

python

运行

import json
import datetime
import time
import requests
from sqlalchemy import create_engine
import csv
import pandas as pd

作用

  • 引入数据解析、网络请求、时间处理、数据库操作等所需库。
  • requests:发送 HTTP 请求获取网页数据。
  • sqlalchemy:连接和操作 MySQL 数据库。
  • pandas:处理 CSV 文件和数据清洗。

潜在问题

  • 未处理requests的超时(可能导致程序卡死)。
  • 数据库密码直接写死在代码中(存在安全风险)。

二、核心爬取函数 scraw(code)

python

运行

def scraw(code):url = f'http://www.nmc.cn/rest/weather?stationid={code}&_=1675259309000'response = requests.get(url, headers=headers)try:data = json.loads(response.text)info = data['data']passed = data['data']['passedchart']real = data['data']['real']tempchart = data['data']['tempchart']predict = data['data']['predict']['detail']# 解析24小时天气数据并写入CSVfor i in passed:csv.writer(csv_obj).writerow([names[inx], ...])# 解析实时天气数据并写入CSVcsv.writer(csv_obj2).writerow([names[inx], ...])# 解析7天温度数据并写入CSVfor i in tempchart:csv.writer(csv_obj3).writerow([names[inx], ...])# 解析预报数据并写入CSVfor i in predict:csv.writer(csv_obj4).writerow([names[inx], ...])except:print(f'{code}爬取失败')

功能拆解

  1. URL 构造

    • 拼接城市代码(stationid)和时间戳参数(_),可能用于防止缓存。
    • 问题:时间戳硬编码(1675259309000),未动态生成,可能导致请求失效。
  2. 数据解析

    • 通过json.loads()解析 JSON 响应,提取passedchart(历史数据)、real(实时数据)等字段。
    • 风险:假设 JSON 结构固定,若网站接口变更会导致解析失败(需添加容错处理)。
  3. CSV 写入

    • 循环写入不同类型数据到 4 个 CSV 文件(data24h.csvdataday.csv等)。
    • 问题names[inx]依赖全局变量inx,多线程环境下可能引发线程安全问题。

三、降雨量爬取函数 scraw_rain24h() & scraw_rain1h()

python

运行

def scraw_rain24h():url = f'http://www.nmc.cn/rest/real/rain/hour24/{date}?_={times}'csv_obj5 = open('csv/rain24h.csv', 'w', ...)response = requests.get(url, headers=headers)data = json.loads(response.text)raindata = data['data']['data']for i in raindata:csv.writer(csv_obj5).writerow([i[0]+i[1], i[5]])csv_obj5.close()def scraw_rain1h():# 逻辑与scraw_rain24h()类似,仅URL和CSV文件不同

关键细节

  • URL 参数date由主程序生成(格式为YYYYMMDD08),times为当前时间戳(动态生成)。
  • 数据结构:降雨量数据通过i[0]+i[1]拼接城市名(假设i[0]为省,i[1]为市),i[5]为降雨量。
  • 问题:未处理城市名重复或异常数据(如i[0]i[1]为空)。

四、数据库存储函数 save()

python

运行

def save():DB_STRING = 'mysql+pymysql://root:mysql@127.0.0.1:3306/tianqi'engine = create_engine(DB_STRING)# 读取CSV文件df = pd.read_csv("csv/data24h.csv")df2 = pd.read_csv("csv/dataday.csv")# ... 读取其他CSV文件# 数据清洗df = df.drop('24h降雨量', axis=1)df2 = df2[df2['体感温度'] != 9999]df3 = df3[df3['最高温度'] != 9999]# 写入数据库df.to_sql('24h', con=engine, if_exists='replace', index=False)# ... 写入其他DataFrame

功能说明

  1. 数据库连接

    • 使用 SQLAlchemy 创建数据库引擎,连接本地 MySQL 的tianqi数据库。
    • 风险:密码mysql硬编码,需通过环境变量或配置文件管理。
  2. 数据清洗

    • 删除无效列(如24h降雨量)和值为9999的行(假设9999为错误值)。
    • 问题:清洗逻辑分散,未统一处理(如其他 CSV 文件可能也存在无效值)。
  3. 数据写入

    • 使用to_sql批量写入,if_exists='replace'会覆盖表数据(可能导致历史数据丢失)。

五、主程序逻辑(if __name__ == '__main__'

python

运行

if __name__ == '__main__':df = pd.read_csv('csv/citycode.csv')codes = df.code.tolist()names = df.城市.tolist()date = time.strftime('%Y%m%d', time.gmtime()) + '08'times = int(time.time() * 1000)headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; ...)'}# 初始化CSV文件csv_obj = open('csv/data24h.csv', 'w', ...)# ... 初始化其他CSV文件for inx, i in enumerate(codes):scraw(i)print(f"{names[inx]}爬取完毕")# 关闭CSV文件csv_obj.close()# ... 关闭其他CSV文件scraw_rain24h()scraw_rain1h()save()

流程分析

  1. 准备阶段

    • 读取城市代码表(citycode.csv),获取codes(城市代码)和names(城市名)。
    • 生成date(当前日期 +08,可能为北京时间时区调整)和times(毫秒级时间戳)。
  2. 爬取阶段

    • 循环调用scraw(i)爬取每个城市的数据,依赖全局变量inxnames
    • 问题:未控制爬取频率(可能触发网站反爬机制),建议添加time.sleep()
  3. 收尾阶段

    • 关闭 CSV 文件句柄(需确保在异常情况下也能关闭,建议用with语句)。
    • 爬取降雨量数据并保存到数据库。

六、整体问题总结与改进方向

模块问题改进建议
爬取逻辑硬编码时间戳、未处理反爬动态生成时间戳,添加请求头(如Referer)、限制爬取频率
异常处理全局except捕获,无详细日志细化异常类型,使用logging模块记录错误信息
资源管理CSV 文件未用with语句,可能泄漏资源改用with open(...) as f管理文件
数据安全数据库密码硬编码使用环境变量(如os.getenv())或配置文件
代码可维护性全局变量耦合严重,逻辑分散将功能封装为类,分离爬取、解析、存储逻辑
扩展性难以为新城市或数据类型扩展设计可配置的爬取规则和字段映射

通过分块优化,可显著提升代码的健壮性、可维护性和安全性,同时降低对目标网站的影响。

 完整代码:

import json
import datetime
import time
import requests
from sqlalchemy import create_engine
import csv
import pandas as pddef scraw(code):# 发送 HTTP 请求,获取网页内容url = f'http://www.nmc.cn/rest/weather?stationid={code}&_=1675259309000'response = requests.get(url, headers=headers)try:data = json.loads(response.text)info = data['data']# 24小时天气情况passed = data['data']['passedchart']# 一天real = data['data']['real']# 最近七天最高低温度tempchart = data['data']['tempchart']# 预测predict = data['data']['predict']['detail']for i in passed:humidity = i['humidity']  # 相对湿度pressure = i['pressure']  # 空气压力rain1h = i['rain1h']  #rain24h = i['rain24h']  #temperature = i['temperature']  # 温度windDirection = i['windDirection']windSpeed = i['windSpeed']time = i['time']tempDiff = i['tempDiff']  # 体感温度csv.writer(csv_obj).writerow([names[inx],humidity, pressure, rain1h, rain24h, temperature, windDirection, windSpeed, time, tempDiff])csv.writer(csv_obj2).writerow([names[inx],datetime.datetime.now().date(), real['weather']['airpressure'], real['weather']['feelst'],real['weather']['humidity'], real['weather']['info'], real['weather']['rain'], real['weather']['temperature'],real['wind']['direct'], real['wind']['power'], real['wind']['speed']])for i in tempchart:time = i['time']max_temp = i['max_temp']min_temp = i['min_temp']csv.writer(csv_obj3).writerow([names[inx],time, max_temp, min_temp])for i in predict:date = i['date']temperatureday = i['day']['weather']['temperature']temperaturenight = i['night']['weather']['temperature']wind = i['day']['wind']['direct']csv.writer(csv_obj4).writerow([names[inx],date, temperatureday, temperaturenight, wind])except:print(f'{code}爬取失败')def scraw_rain24h():url = f'http://www.nmc.cn/rest/real/rain/hour24/{date}?_={times}'csv_obj5 = open('csv/rain24h.csv', 'w', encoding="utf-8",newline='')response = requests.get(url, headers=headers)data = json.loads(response.text)print(data)raindata = data['data']['data']csv.writer(csv_obj5).writerow(["城市",'降雨量'])for i in raindata:csv.writer(csv_obj5).writerow([i[0] +i[1], i[5]])print('爬取数据完毕')csv_obj5.close()def scraw_rain1h():url = f'http://www.nmc.cn/rest/real/rain/hour1/{date}?_={times}'csv_obj6 = open('csv/rain1h.csv', 'w', encoding="utf-8", newline='')response = requests.get(url, headers=headers)data = json.loads(response.text)raindata = data['data']['data']csv.writer(csv_obj6).writerow(["城市", '降雨量'])for i in raindata:csv.writer(csv_obj6).writerow([i[0] + i[1], i[5]])print('爬取数据完毕')csv_obj6.close()def save():# 存入数据库DB_STRING = 'mysql+pymysql://root:mysql@127.0.0.1:3306/tianqi'engine = create_engine(DB_STRING)df = pd.read_csv("csv/data24h.csv")df2 = pd.read_csv("csv/dataday.csv")df3 = pd.read_csv("csv/tempchart.csv")df4 = pd.read_csv("csv/predict.csv")df5 = pd.read_csv("csv/rain24h.csv")df6 = pd.read_csv("csv/rain1h.csv")#删除不正常值# 删除部分列值等于9999的行df = df.drop('24h降雨量',axis=1)df2 = df2[df2['体感温度'] != 9999]df3 = df3[df3['最高温度'] != 9999]df.to_sql('24h', con=engine, if_exists='replace',index=False)df2.to_sql('day', con=engine, if_exists='replace',index=False)df3.to_sql('tempchart', con=engine, if_exists='replace',index=False)df4.to_sql('predict', con=engine, if_exists='replace',index=False)df5.to_sql('rain24h', con=engine, if_exists='replace',index=False)df6.to_sql('rain1h', con=engine, if_exists='replace',index=False)print('保存数据库完毕')if __name__ == '__main__':df = pd.read_csv('csv/citycode.csv')codes = df.code.tolist()names = df.城市.tolist()#北京# codes = [54511]# names = ['北京']date = time.strftime('%Y%m%d', time.gmtime()) +'08'times = int(time.time() * 1000)# # 设置请求头部信息,避免被识别为爬虫headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}csv_obj = open('csv/data24h.csv', 'w', encoding="utf-8",newline='')csv_obj2 = open('csv/dataday.csv', 'w', encoding="utf-8", newline='')csv_obj3 = open('csv/tempchart.csv', 'w', encoding="utf-8", newline='')csv_obj4 = open('csv/predict.csv', 'w', encoding="utf-8", newline='')csv.writer(csv_obj).writerow(["城市","相对湿度", "气压", "一小时降雨量","24h降雨量", "温度", "风向", "风速","时间",'体感温度'])csv.writer(csv_obj2).writerow(["城市","日期","气压", '体感温度',"相对湿度","天气情况","一小时降雨量","温度", "风向", "风强度","风速"])csv.writer(csv_obj3).writerow(["城市","日期","最高温度", '最低温度'])csv.writer(csv_obj4).writerow(["城市","日期","白天温度", '夜晚温度',"风向"])for inx,i in enumerate(codes):scraw(i)print(f"{names[inx]}爬取完毕")csv_obj.close()csv_obj2.close()csv_obj3.close()csv_obj4.close()scraw_rain24h()scraw_rain1h()save()

 

import csv
import json
import requests
# 设置请求头部信息,避免被识别为爬虫headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}# 发送 HTTP 请求,获取网页内容url = 'http://www.nmc.cn/rest/province/all?_=1678112903659'
response = requests.get(url, headers=headers)
data = json.loads(response.text)
csv_obj = open('allcsv/citycode.csv', 'w', encoding="utf-8", newline='')
csv.writer(csv_obj).writerow(['城市','code'])
for i in data:code = i['code']url = f'http://www.nmc.cn/rest/province/{code}?_=1677854971362'response = requests.get(url, headers=headers)data = json.loads(response.text)for x in data:csv.writer(csv_obj).writerow([x['city'], x['code']])csv_obj.close()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/84273.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/84273.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/84273.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫(三):BeautifulSoup库

1. BeautifulSoup是什么? BeautifulSoup 是一个 Python 库,专门用来解析 HTML 或 XML 文件,方便我们提取数据。它能把网页源代码转换成树形结构,让我们可以轻松查找、修改内容,并自动处理编码问题(如 Unic…

AI电销机器人智能的发展趋势是什么?

AI电销机器人智能的发展趋势是什么?电销机器人智能的发展前景怎么样?随着互联网技术的不断发展,AI电销机器人智能已经成为了许多企业实现销售数字化转型的重要工具,我们一起来看看。 AI电销机器人正突破传统语音机械应答的边界&a…

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…

C++_哈希表

本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…

Mac M芯片 RAG 极简流程 安装 ragflow + LM studio

本文基于 【【知识科普】【纯本地化搭建】【不本地也行】DeepSeek RAGFlow 构建个人知识库】 https://www.bilibili.com/video/BV1WiP2ezE5a/?share_sourcecopy_web&vd_source9a55f12dd64d8e30ab6c0efc62844343 1 .docker-compose yml文件修改,指定平台 platform: linux/…

Rsync+inotify+nfs实现数据实时备份方案

技术栈 NFS是 Network File System的简写,即网络文件系统。NFS的优点是内核直接支持,部署简单、运行稳定,协议简单、传输效率高。缺点是仅依靠IP地址或主机名来决定用户能否挂载共享目录,容易出现单点故障。 rsync是linux系统下的…

Vue ⑥-路由

单页应用程序 单页应用程序,即 Single-Page Application,简称 SPA,是一种使用 JavaScript、HTML 和 CSS 构建的 Web 应用程序。SPA 的核心是前端路由,它使得用户在访问网站时,只需加载一次页面,然后通过前…

Hadoop复习(九)

Azkaban工作流管理器 选择 问题 1 判断题 2 / 2 分 工作流是指具有依赖的一组job任务,被依赖的job任务最后执行 正确 错误 问题 2 判断题 2 / 2 分 Azkaban兼容任何版本的Hadoop 正确 错误 问题 3 判断题 2 / 2 分 独立服务器模式下,Azkab…

SpringMVC相关知识(二)

一.重定向和转发 1.ModelandView 设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 页面 : {视图解析器前缀} viewName {视图解析器后缀} 相关代码&#xff1a; <!-- 视图解析器 --> <bean class"org.springframework.web.servlet.vi…

std::ratio 简单使用举例

author: hjjdebug date: 2025年 06月 09日 星期一 14:28:40 CST descrip: std::ratio 简单使用举例 文章目录 1. 先看一个简单的例子 1/2/1/35/62 std::ratio 的手册页3. std::ratio_add 到底是什么呢&#xff1f;4. 代码注释5. 加深理解.6. 自定义的std::ratio 与 std::ratio_…

Docker 优势与缺点全面解析:容器技术的利与弊

在当今云计算、微服务、DevOps盛行的时代&#xff0c;Docker 几乎成了开发者、运维工程师的标配工具之一。自2013年诞生以来&#xff0c;Docker 以其轻量、快速、易移植的特点&#xff0c;彻底改变了应用的构建、交付与部署方式。 但任何技术都有两面性&#xff0c;Docker 也不…

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…

使用Redis作为缓存优化ElasticSearch读写性能

在现代数据密集型应用中,ElasticSearch凭借其强大的全文搜索能力成为许多系统的首选搜索引擎。然而,随着数据量和查询量的增长,ElasticSearch的读写性能可能会成为瓶颈。本文将详细介绍如何使用Redis作为缓存层来显著提升ElasticSearch的读写性能,包括完整的架构设计、详细…

获取wordpress某个栏目的内容数量

获取wordpress某个栏目的内容数量 <?php // 将以下 8 改成你的分类 ID 即可echo get_category(8)->count;?> 在制作wordpress模板时&#xff0c;有时会需要调用某个分类目录下的所有内容数量&#xff0c;通过这段简洁的代码就可以实现。 给WordPress自定义字段加…

uniapp 安卓 APP 后台持续运行(保活)的尝试办法

在移动应用开发领域&#xff0c;安卓系统的后台管理机制较为复杂&#xff0c;应用在后台容易被系统回收&#xff0c;导致无法持续运行。对于使用 Uniapp 开发的安卓 APP 来说&#xff0c;实现后台持续运行&#xff08;保活&#xff09;是很多开发者面临的重要需求&#xff0c;比…

深度学习——知识提炼

第一部分&#xff1a;引言与背景——为什么需要知识提炼&#xff1f; 一、模型压缩的背景 随着深度学习的发展&#xff0c;模型变得越来越大&#xff08;如 ResNet152、BERT、ViT、GPT 等&#xff09;&#xff0c;其参数量动辄数亿甚至上百亿。这些大模型虽然性能强大&#x…

开源之夏·西安电子科技大学站精彩回顾:OpenTiny开源技术下沉校园,点燃高校开发者技术热情

开源之夏2025编程活动正在如火如荼的进行中&#xff0c;当前也迎来了报名的倒计时阶段&#xff0c;开源之夏组织方也通过高校行系列活动进入各大高校&#xff0c;帮助高校开发者科普开源文化、开源活动、开源技术。 6月4日 开源之夏携手多位开源技术大咖、经验型选手走进西安电…

时间复杂度和算法选择

数据范围 时间复杂度 算法选择 n \leq 30 指数级别 O(2^n) 深度优先搜索&#xff08;DFS&#xff09; 剪枝、状态压缩动态规划 n \leq 100 O(n^3) Floyd 算法、动态规划、高斯消元 n \leq 1000 O(n^2) 、 O(n^2 \log n) 动态规划、二分…

数据分析实战2(Tableau)

1、Tableau功能 数据赋能&#xff08;让业务一线也可以轻松使用最新数据&#xff09; 分析师可以直接将数据看板发布到线上自动更新看板自由下载数据线上修改图表邮箱发送数据设置数据预警 数据探索&#xff08;通过统计分析和数据可视化&#xff0c;从数据发现问题&#xf…