网页爬取气象数据转CSV:列对齐与日期优化问题
解决Wunderground气象数据爬取的CSV错位与日期优化问题
我来帮你搞定爬取Wunderground机场气象数据时遇到的CSV数据错位、日期显示不清晰的问题,咱们一步步优化代码:
核心问题分析
你遇到的两个主要问题:
- CSV数据错位:页面表格中部分行的列数和表头不一致,直接写入CSV时会导致列对应混乱
- 日期归属模糊:爬取的每行数据没有明确绑定日期,无法直观知道数据属于哪天
优化方案与代码实现
1. 先导入所需库
import urllib3 from bs4 import BeautifulSoup import csv from datetime import datetime
2. 封装单页爬取函数
把单天数据的爬取逻辑封装成函数,减少重复代码,同时统一处理列数和日期:
def scrape_daily_weather(airport_code, year, month, day): # 构造带日期的请求URL url = f"https://www.wunderground.com/history/airport/{airport_code}/{year}/{month}/{day}/DailyHistory.html?req_city=&req_state=&req_statename=&reqdb.zip=&reqdb.magic=&reqdb.wmo=" http = urllib3.PoolManager() response = http.request("GET", url) soup = BeautifulSoup(response.data, "lxml") # 定位气象表格区域 table_div = soup.find('div', {"class":"high-res"}) if not table_div: print(f"⚠️ 未找到{year}-{month}-{day}的有效数据") return [], [] # 获取表头,确定标准列数 header_row = table_div.find('tr') if not header_row: return [], [] headers = [th.strip() for th in header_row.stripped_strings] standard_col_count = len(headers) # 处理每一行数据 daily_data = [] # 跳过表头行,遍历数据行 for tr in table_div.findAll('tr')[1:]: row_data = [td.strip() for td in tr.stripped_strings] # 统一列数:不足补空字符串,多余则截断到标准列数 if len(row_data) < standard_col_count: row_data += [''] * (standard_col_count - len(row_data)) elif len(row_data) > standard_col_count: row_data = row_data[:standard_col_count] # 添加标准化日期到行首(格式:YYYY-MM-DD) row_date = datetime(year, month, day).strftime("%Y-%m-%d") row_data.insert(0, row_date) daily_data.append(row_data) return headers, daily_data
3. 主逻辑:遍历机场和日期,整合数据并写入CSV
# 替换成你的机场代码列表,比如 ['KJFK', 'LAX', 'ORD'] airports = ['KJFK'] all_weather_data = [] final_headers = None for airport in airports: # 处理1月(31天) for day in range(1, 32): headers, daily_data = scrape_daily_weather(airport, 2018, 1, day) # 只在首次获取到表头时,添加日期表头并写入 if headers and final_headers is None: final_headers = ['日期'] + headers all_weather_data.append(final_headers) all_weather_data.extend(daily_data) # 处理2月(2018是平年,共28天) for day in range(1, 29): headers, daily_data = scrape_daily_weather(airport, 2018, 2, day) all_weather_data.extend(daily_data) # 写入CSV文件,指定编码和换行符避免乱码/空行问题 with open('weather.csv', 'w', newline='', encoding='utf-8') as file: writer = csv.writer(file) writer.writerows(all_weather_data)
关键优化点说明
- 统一列数:通过表头获取固定列数,对每一行数据做补空或截断操作,确保所有行的列数和表头完全匹配,彻底解决CSV错位问题
- 明确日期标识:把日期(标准化为
YYYY-MM-DD格式)添加到每行数据的开头,让每一条气象数据都能清晰对应到具体日期 - 代码复用:将单页爬取逻辑封装成函数,避免重复写相同的请求、解析代码,后续维护更方便
- 文件写入优化:使用
w模式覆盖写入(而非a追加),确保每次生成干净的文件;指定newline=''避免CSV出现多余空行,encoding='utf-8'保证特殊字符正常显示
内容的提问来源于stack exchange,提问作者SAI RAJESH




