Pandas执行df.to_csv导出csv文件所有行内容相同问题如何解决
问题产生原因
- 链式索引赋值异常:代码中
df['IPcity'][index]类的链式赋值写法不符合Pandas规范,该操作会返回DataFrame的临时副本而非原数据视图,对副本的修改不会作用到原df,最终所有行的新增列会被最后一次赋值结果覆盖,出现内容一致的问题。 - 异常分支全列广播赋值:报错逻辑中的
df['e'] = e会将当前单个异常值广播到整个e列的所有行,直接导致所有行的错误列内容完全相同。 - 保存时机错误:
to_csv被放在循环体内部,每次迭代都会覆盖写入csv文件,前面行的修改结果会被后续迭代覆盖,最终文件仅保留最后一次迭代的写入结果。 - 未提前初始化新增列:IPcity、ASNumber、e等新增列未提前定义,赋值时容易出现类型推导错误或全列默认值填充问题。
解决方案
优化赋值逻辑、保存逻辑即可解决问题,优化后代码如下:
import whois import matplotlib.pyplot as plt import numpy as np import pandas as pd import socket import os import csv import datetime import time import requests from ipwhois import IPWhois from urllib import request from ipwhois.utils import get_countries import tldextract from ipwhois.experimental import bulk_lookup_rdap from ipwhois.hr import (HR_ASN, HR_ASN_ORIGIN, HR_RDAP_COMMON, HR_RDAP, HR_WHOIS, HR_WHOIS_NIR) import ipaddress countries = get_countries(is_legacy_xml=True) df = pd.read_csv('a.csv', nrows=100) # 提前初始化所有新增列 new_cols = ['IPcity', 'ASNumber', 'NetAddr', 'NetCity', 'NetPostCode', 'e'] for col in new_cols: df[col] = '' # 全局设置socket超时 socket.setdefaulttimeout(10) def check_date_type(d): if type(d) is datetime.datetime: return d if type(d) is list: return d[0] for index,row in df.iterrows(): try: DN = row['Domains'] ip = socket.gethostbyname(DN) ipwhois = IPWhois(ip).lookup_whois() # 用官方推荐的.loc索引赋值,确保修改原df df.loc[index, 'IPcity'] = ipwhois['nets'][0].get('city', '') df.loc[index, 'ASNumber'] = ipwhois.get('asn', '') df.loc[index, 'NetAddr'] = ipwhois['nets'][0].get('address', '') df.loc[index, 'NetCity'] = ipwhois.get('city', '') df.loc[index, 'NetPostCode'] = ipwhois['nets'][0].get('postal_code', '') except Exception as e: print(e) # 仅给当前行的错误列赋值 df.loc[index, 'e'] = str(e) # 所有行处理完成后统一保存 ## 保留所有结果(包含错误列) df.to_csv('a_final.csv', index=False) ## 如需拆分成功、失败结果单独保存,可启用下方代码 # df[df['e'] == ''].drop('e', axis=1).to_csv('a1.csv', index=False) # df[df['e'] != ''].to_csv('a2.csv', index=False)
内容的提问来源于stack exchange,提问作者Loknath Basak
相关产品推荐
相关产品推荐

