You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

处理OpenFoodFacts TSV大文件的两类ParserError排查与解决

问题描述

处理10GB的Tab分隔数据文件时,已将错误分隔符\n\t替换为\t,并根据字段规则定义了列类型,但使用pandas读取时遇到两类问题:

  1. ParserWarning:提示第1715281行预期209个字段,实际检测到239个;但用linecache.getline读取该行并按\t分割后,字段数为209,与列数一致。
  2. ValueError:无法解析字符串https://images.openfoodfacts.org/images/products/356/007/117/1049/front_fr.3.200.jpg,仅该行出现此错误。

具体疑问:

  1. 为何已修正分隔符,仍会出现第1715281行的解析错误?
  2. 使用getline结合split对比字段数是否为有效的排查方法?
  3. 如何解决仅某一行出现的URL字符串解析失败问题?

相关代码

import os.path
import pandas as pd
import numpy as np
import linecache

# 生成文件路径
data_local_path = os.getcwd() + '\\'
csv_filename = 'en.openfoodfacts.org.products.csv'
csv_local_path = data_local_path + csv_filename

# 生成修正后文件路径
clean_filename = 'en.off.corrected.csv'
clean_local_path = data_local_path + clean_filename

# 修正错误分隔符
if not os.path.isfile(clean_local_path):
    with open(csv_local_path, 'r',encoding='utf-8') as csv_file, open(clean_local_path, 'a', encoding='utf-8') as clean_file:
        for row in csv_file:
            clean_file.write(row.replace('\n\t', '\t'))

# 定义列类型
column_names = pd.read_csv(clean_local_path, sep='\t', encoding = 'utf-8', nrows=0).columns.values
column_types = {col: 'Int64' for col in column_names if col.endswith(('_t', '_n'))}
column_types |= {col: float for col in column_names if col.endswith(('_100g', '_serving'))}
column_types |= {col: str for col in column_names if not col.endswith(('_t', '_n', '_100g', '_serving', '_tags'))}

print("number of columns detected: ",len(column_names)) # 输出:209

# 加载数据
data = pd.read_csv(clean_local_path, sep='\t', encoding='utf_8', 
                   dtype=column_types, parse_dates=[col for col in column_names if col.endswith('_datetime')],
                   on_bad_lines='warn'
                  )
data.info()

错误信息

...\AppData\Local\Temp\ipykernel_2824\611804071.py:2: ParserWarning: Skipping line 1715281: expected 209 fields, saw 239

  data = pd.read_csv(clean_local_path, sep='\t', encoding='utf_8',
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File lib.pyx:2391, in pandas._libs.lib.maybe_convert_numeric()

ValueError: Unable to parse string "https://images.openfoodfacts.org/images/products/356/007/117/1049/front_fr.3.200.jpg"

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
Cell In[6], line 2
      1 # Load the data
----> 2 data = pd.read_csv(clean_local_path, sep='\t', encoding='utf_8', 
      3                    dtype=column_types, parse_dates=[col for (col) in column_names if col.endswith('_datetime')],
      4                    on_bad_lines='warn'
      5                   )
      6 # display info
      7 data.info()

...(中间栈信息省略)

File lib.pyx:2433, in pandas._libs.lib.maybe_convert_numeric()

ValueError: Unable to parse string "https://images.openfoodfacts.org/images/products/356/007/117/1049/front_fr.3.200.jpg" at position 1963

排查第1715281行的代码

# 获取告警对应的行
line = linecache.getline(csv_local_path,1715281)
# 按Tab分割
split_list = line.split('\t')

print("concerning Parser Warning: Skipping line 1715281: expected 209 fields, saw 239")
print("number of data detected in the raw 1715281: ",len(split_list)) # 输出:209
print ("number of columns detected in CSV: ",len(column_names)) # 输出:209

解答

1. 第1715281行解析错误的原因

  • 字段内部未转义的换行符:pandas解析器默认按\n/\r\n识别行尾,若该行某个字段内部包含未被引号包裹的换行符,会被误判为多行,导致统计出更多字段;而linecache.getline是按物理行读取,会把包含内部换行的字段当成一行,因此split后字段数正确。
  • 不可见控制字符:文件中可能存在\r、\x00等不可见字符,干扰解析器的字段分割逻辑,但split('\t')对这类字符不敏感,结果不受影响。
  • 分隔符修正不彻底:仅替换了\n\t,但可能存在\r\t等其他错误分隔符组合未被处理。

2. getline+split是否为有效排查方法?

属于半有效手段:

  • 优点:快速验证物理行的字段数量是否匹配,排除肉眼可见的分隔符问题。
  • 缺点:无法模拟pandas解析器的完整逻辑——解析器会处理引号包裹的字段、转义字符、行尾识别规则等,而split('\t')只是简单分割,会忽略这些场景(比如字段内的\t被引号包裹时,pandas会识别为一个字段,但split会直接拆分)。

更有效的排查方式:用csv.reader指定与pandas一致的参数(分隔符、引号规则)读取该行,查看解析后的字段数。

3. 解决URL解析失败的问题

该错误是列类型定义错误导致:你将某个应属于字符串类型的列,错误定义成了数值类型(Int64或float),当该行该字段出现URL字符串时,pandas尝试转换为数值失败,抛出异常。

解决步骤:

  1. 定位错误列:根据错误信息中的position 1963,找到column_names[1963]对应的列名,检查你的类型映射规则是否错误匹配了该列。
  2. 修正类型规则:确保该列被定义为str类型,比如调整后缀匹配逻辑,避免误将字符串列归类为数值列。
  3. 临时应急方案:若暂时无法定位错误列,可在read_csv中设置on_bad_lines='skip'跳过错误行;或对数值列使用converters参数,指定errors='coerce'将无法转换的值设为NaN。

内容的提问来源于stack exchange,提问作者user30252915

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 08:49:59