Scrapy爬取CSV数据插入MySQL无报错无数据,疑类型不匹配
嘿,我来帮你搞定这个头疼的问题!你推测的CSV全字符串类型确实大概率是元凶,但还有几个容易忽略的坑也得一起查,咱们一步步来拆解:
1. 先确认事务提交——90%的“没数据不报错”都栽在这
很多时候不是插入语句的问题,而是你忘了提交事务!MySQL默认是关闭自动提交的,如果你用pymysql这类库操作,必须手动调用提交命令,不然哪怕执行成功,数据也只是存在内存里,不会写入数据库:
import pymysql # 建立数据库连接 conn = pymysql.connect(host='localhost', user='你的用户名', password='你的密码', db='目标数据库') cursor = conn.cursor() try: # 假设这里是你的插入语句和参数 insert_sql = "INSERT INTO your_table (col1, col2) VALUES (%s, %s)" cursor.execute(insert_sql, (val1, val2)) conn.commit() # 划重点!没这行等于白忙活 except Exception as e: conn.rollback() # 出错就回滚,避免脏数据 print(f"插入出错:{e}") finally: cursor.close() conn.close()
2. 处理CSV字符串与数据库字段的类型不匹配
CSV里的所有值都是字符串,但你的MySQL表字段可能是整数、日期、浮点型等,直接插入会触发隐式转换失败——有时候MySQL不会报错,只会默默忽略或者插入空值。你得手动做类型转换:
- 数字类型:用
int()/float()转换,记得先判断空字符串 - 日期类型:用
datetime模块解析成MySQL能识别的格式 - 空值:把CSV里的空字符串转成
None,不然会插入空字符串而不是数据库的NULL
举个实际例子,假设你的表有id(INT)、price(FLOAT)、create_time(DATETIME)字段,CSV读出来的都是字符串,转换代码如下:
import csv import datetime with open('爬取的数据.csv', 'r', encoding='utf-8') as f: reader = csv.DictReader(f) for row in reader: # 逐个字段做类型转换 processed_data = { 'id': int(row['id']) if row['id'].strip() else None, 'price': float(row['price']) if row['price'].strip() else None, 'create_time': datetime.datetime.strptime(row['create_time'], '%Y-%m-%d %H:%M:%S') if row['create_time'].strip() else None, 'title': row['title'] # 字符串类型直接用 } # 执行插入 insert_sql = "INSERT INTO goods (id, price, create_time, title) VALUES (%s, %s, %s, %s)" cursor.execute(insert_sql, (processed_data['id'], processed_data['price'], processed_data['create_time'], processed_data['title'])) conn.commit() # 别忘了提交!
3. 打印实际执行的SQL,排查语句问题
如果还是没数据,建议打印出最终发送给MySQL的SQL语句,直接在数据库客户端执行,就能一眼看出问题:
# 执行前打印SQL和参数,方便排查 print(cursor.mogrify(insert_sql, processed_data)) cursor.execute(insert_sql, processed_data)
比如你可能会发现CSV里的日期格式和数据库要求的不一样,或者字段名写错了,这些细节光看代码很难发现。
4. 先确认CSV数据是否被正确读取
有时候CSV文件看起来有数据,但实际读出来是空行,或者分隔符不对(比如数据里有逗号但没加引号),导致csv.DictReader没正确解析。可以先打印前几行数据确认:
with open('爬取的数据.csv', 'r', encoding='utf-8') as f: reader = csv.DictReader(f) for i, row in enumerate(reader): print(f"第{i+1}行数据:{row}") if i == 4: # 只打印前5行就行 break
按照这几步排查,基本就能找到问题所在啦!
内容的提问来源于stack exchange,提问作者Deba
相关产品推荐
相关产品推荐

