Python pd.read_csv读取csv报Too many columns specified错误排查
错误原因
- 传入
pd.read_csv()的目标地址是HTML网页,不是纯文本CSV数据。该页面包含大量HTML标签、前端渲染代码,pandas逐块读取时,碰到不含逗号分隔符的HTML代码行,会判定该行仅1列,和你指定的20个列名数量不匹配,直接触发报错。 - HURDAT2原始数据本身不是等列数的规整CSV结构:文件内交替存在两类合法行,一类是单条飓风的元信息头行,仅3个有效字段;另一类是逐6小时的观测记录行,才对应你定义的20个字段。直接强制按全文件20列读取,碰到短的头行也会触发列数不匹配错误。
- 代码里已经定义了专门适配该数据格式的
readHURDAT2()解析函数,但后续读取逻辑没有调用这个函数,反而直接用pandas硬读格式不匹配的内容,逻辑冲突。
修复方案
- 第一步先获取干净的纯文本数据:不要直接把HTML页面地址传给
pd.read_csv(),先请求地址拿到页面内容,提取页面中<pre>标签包裹的原始纯文本数据,剔除所有HTML标签垃圾内容。 - 不要直接用固定列数参数硬读全文件:要么直接复用代码里已经写好的
readHURDAT2()函数处理提取到的纯文本数据,拿到结构化结果;要么逐行遍历纯文本内容,先识别行类型:如果是飓风元信息头行就单独存储当前飓风的基础属性,如果是观测记录行再按20个字段拆分,和列名匹配后存入结果集。 - 不要通过加
on_bad_lines='skip'这类参数跳过报错行,这类被判定为“列数不对”的行要么是需要的头行数据,要么是HTML垃圾内容,直接跳过会导致数据缺失或者脏数据混入。
可参考的实现代码:
import requests import re import pandas as pd from io import StringIO url = 'https://www.aoml.noaa.gov/hrd/hurdat/hurdat2.html' columnnames= ['list out each of the 20 column names'] # 替换为实际使用的20个列名 # 拉取并清洗出纯数据文本 resp = requests.get(url, timeout=10) # 提取pre标签内的原始数据,剔除HTML标签 raw_text = re.search(r"<pre>(.*?)</pre>", resp.text, re.S).group(1).strip() records = [] current_storm = {} for line in StringIO(raw_text): line = line.strip() if not line: continue parts = [i.strip() for i in line.split(",")] # 识别飓风头行:以AL/EP/CP开头的ID,共3个有效字段 if len(parts) >=3 and parts[0][:2] in ("AL", "EP", "CP") and parts[0][2:].isdigit(): current_storm = { "storm_id": parts[0], "storm_name": parts[1], "track_entry_count": int(parts[2]) } else: # 解析观测行,和当前飓风信息合并 obs_row = dict(zip(columnnames, parts[:len(columnnames)])) obs_row.update(current_storm) records.append(obs_row) # 最终拿到结构化的DataFrame result_df = pd.DataFrame(records)
内容的提问来源于stack exchange,提问作者help_me
相关产品推荐
相关产品推荐

