从TrueCar抓取车辆数据插入MySQL失败:数据异常及建表问题修复
问题修复方案
核心问题分析
- 未创建MySQL表:代码中缺少创建
car表的逻辑,直接执行插入操作会触发表不存在的错误。 - 字典列表遍历错误:遍历
data时用for price,miles in data,实际会遍历字典的键名(即'price'和'miles'),而非对应的数据值。 - 数据未清洗:提取的价格含
$、逗号,里程含逗号和miles字样,无法直接存入数据库或影响后续使用。 - SQL注入风险:用字符串格式化拼接SQL语句,存在安全隐患。
具体修复步骤
1. 提前创建MySQL表
连接数据库后,先执行建表语句(避免表不存在的问题):
cursor.execute(""" CREATE TABLE IF NOT EXISTS car ( id INT AUTO_INCREMENT PRIMARY KEY, price DECIMAL(10,2) NOT NULL, mileage INT NOT NULL ) """) cnx.commit()
这里用DECIMAL存储价格(适配金额精度),INT存储里程,同时添加自增主键方便数据管理。
2. 修复数据提取与清洗
修改爬虫逻辑,去除非数字字符并转换为对应数据类型:
for card in soup.select('[class="card-content vehicle-card-body order-3 vehicle-card-carousel-body"]'): # 清洗价格:去掉$和逗号,转为浮点型 price_text = card.select_one('[class="heading-3 margin-y-1 font-weight-bold"]').text.strip() price = float(price_text.replace('$', '').replace(',', '')) # 清洗里程:提取数字部分,去掉逗号,转为整数 miles_text = card.select_one('div[class="d-flex w-100 justify-content-between"]').text.strip() miles = int(miles_text.split(' ')[0].replace(',', '')) data.append({ 'price': price, 'miles': miles })
3. 正确遍历字典列表+参数化查询
修改插入逻辑,避免遍历键名,同时用参数化查询防止SQL注入:
for item in data: cleaned_price = item['price'] cleaned_miles = item['miles'] # 参数化查询,占位符%s无需加引号 cursor.execute("INSERT INTO car (price, mileage) VALUES (%s, %s)", (cleaned_price, cleaned_miles)) # 批量提交更高效,无需每次循环都commit cnx.commit()
完整修复代码
import requests from bs4 import BeautifulSoup import mysql.connector car = input("输入车型:") base_url = 'https://www.truecar.com/used-cars-for-sale/listings/' url = base_url + car try: r = requests.get(url) r.raise_for_status() # 检查请求是否成功 soup = BeautifulSoup(r.text, 'html.parser') data = [] for card in soup.select('[class="card-content vehicle-card-body order-3 vehicle-card-carousel-body"]'): # 处理价格提取异常 price_elem = card.select_one('[class="heading-3 margin-y-1 font-weight-bold"]') if not price_elem: continue price_text = price_elem.text.strip() price = float(price_text.replace('$', '').replace(',', '')) # 处理里程提取异常 miles_elem = card.select_one('div[class="d-flex w-100 justify-content-between"]') if not miles_elem: continue miles_text = miles_elem.text.strip() miles = int(miles_text.split(' ')[0].replace(',', '')) data.append({ 'price': price, 'miles': miles }) print("提取到的数据:", data) # 连接数据库 cnx = mysql.connector.connect( user='root', password='', host='127.0.0.1', database='truecar' ) cursor = cnx.cursor() # 创建表(不存在则创建) cursor.execute(""" CREATE TABLE IF NOT EXISTS car ( id INT AUTO_INCREMENT PRIMARY KEY, price DECIMAL(10,2) NOT NULL, mileage INT NOT NULL ) """) cnx.commit() # 插入数据 for item in data: cursor.execute( "INSERT INTO car (price, mileage) VALUES (%s, %s)", (item['price'], item['miles']) ) cnx.commit() print("数据插入成功!") except requests.exceptions.RequestException as e: print(f"请求出错:{e}") except mysql.connector.Error as e: print(f"数据库错误:{e}") except Exception as e: print(f"其他错误:{e}") finally: # 确保关闭数据库连接 if 'cnx' in locals() and cnx.is_connected(): cursor.close() cnx.close()
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

