Python 爬虫实战:汽车之家 50,524 条车型数据入库,MySQL 与 MongoDB 性能对比

📅 2026/7/5 22:21:47
Python 爬虫实战:汽车之家 50,524 条车型数据入库,MySQL 与 MongoDB 性能对比
Python 爬虫实战汽车之家 50,524 条车型数据入库与数据库选型指南1. 爬虫数据存储的核心挑战在数据驱动的互联网时代爬虫技术已成为获取信息的重要手段。但许多开发者在完成数据抓取后往往面临一个关键问题如何高效、可靠地存储这些海量数据以汽车之家50,524条车型数据为例我们不仅要考虑存储效率还需关注后续查询和分析的便捷性。传统做法是将数据简单写入CSV或文本文件但当数据量达到数万条甚至更多时这种方式的局限性就暴露无遗数据查询效率低下缺乏结构化存储能力难以支持并发读写数据安全性和完整性无法保障数据库选型的三个关键维度写入性能爬虫通常需要快速存储大量数据查询效率后续分析需要高效的数据检索灵活性应对可能变化的字段和数据结构2. 汽车之家爬虫实战数据抓取与清洗2.1 目标网站分析与请求构造汽车之家网站采用传统的HTML结构与动态加载相结合的方式展示车型数据。我们的爬虫需要处理两种主要页面车型列表页包含品牌、车系和基础车型信息车型详情页包含具体参数配置import requests from bs4 import BeautifulSoup import json headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, X-Forwarded-For: f{random.randint(1,255)}.{random.randint(1,255)}.{random.randint(1,255)}.{random.randint(1,255)} } def get_brand_list(): 获取所有品牌信息 url https://car.autohome.com.cn/AsLeftMenu/As_LeftListNew.ashx params {typeId:1, brandId:0, fctId:0, seriesId:0} response requests.get(url, headersheaders, paramsparams) soup BeautifulSoup(response.text, html.parser) return [{brand_id: li.get(id).replace(b,), name: li.a.text} for li in soup.find_all(li)]2.2 数据解析与异常处理汽车之家的数据分布在HTML标签和JSON接口中我们需要结合多种解析方式def parse_series_data(brand_id): 解析车系数据 url fhttps://car.autohome.com.cn/price/brand-{brand_id}.html response requests.get(url, headersheaders) soup BeautifulSoup(response.text, html.parser) series_data [] for dl in soup.find_all(class_list-dl): for dd in dl.find_all(class_list-dl-text): for a in dd.find_all(a): series_id re.findall(\d, a.get(href))[0] series_data.append({ series_id: series_id, name: a.text, brand_id: brand_id }) return series_data常见反爬应对策略随机User-Agent轮换IP代理池构建请求频率控制重要数据校验机制3. MySQL与MongoDB技术对比3.1 架构设计差异特性MySQLMongoDB数据模型关系型严格Schema文档型灵活Schema扩展方式垂直扩展水平扩展事务支持ACID完备4.0版本支持多文档事务索引机制B树索引B树索引支持多键、全文等适用场景结构化数据复杂查询半结构化数据快速迭代3.2 性能基准测试(50,524条数据)我们在相同硬件环境下对两种数据库进行了对比测试写入测试结果MySQL批量插入约12秒(每次1000条)MongoDB批量插入约4秒(每次1000条)存储空间占用MySQL(InnoDB)约78MBMongoDB约92MB典型查询响应时间1. 按品牌分组统计车型数量 - MySQL: 0.8s - MongoDB: 1.2s 2. 模糊查询车型名称包含SUV的记录 - MySQL: 1.5s - MongoDB: 0.6s (使用全文索引)4. MySQL实战结构化数据存储方案4.1 数据库表设计合理的表结构设计对后续查询性能至关重要CREATE TABLE car_brand ( id int(11) NOT NULL AUTO_INCREMENT, brand_id varchar(20) NOT NULL, name varchar(50) NOT NULL, PRIMARY KEY (id), UNIQUE KEY idx_brand_id (brand_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE car_series ( id int(11) NOT NULL AUTO_INCREMENT, series_id varchar(20) NOT NULL, brand_id varchar(20) NOT NULL, name varchar(100) NOT NULL, PRIMARY KEY (id), UNIQUE KEY idx_series_id (series_id), KEY idx_brand_id (brand_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;4.2 高效数据写入技巧使用批量插入和连接池技术显著提升性能import pymysql from pymysql import cursors def save_to_mysql(data_list, table_name): conn pymysql.connect( hostlocalhost, userroot, passwordyourpassword, databasecar_data, cursorclasscursors.DictCursor ) try: with conn.cursor() as cursor: # 构建批量插入SQL keys data_list[0].keys() sql fINSERT INTO {table_name} ({,.join(keys)}) VALUES ({,.join([%s]*len(keys))}) values [tuple(item.values()) for item in data_list] # 每次插入1000条 for i in range(0, len(values), 1000): cursor.executemany(sql, values[i:i1000]) conn.commit() finally: conn.close()提示对于超大规模数据插入考虑使用LOAD DATA INFILE方式比INSERT语句快20-50倍5. MongoDB实战灵活文档存储方案5.1 文档结构设计MongoDB的灵活文档模型特别适合汽车参数这种可能变化的半结构化数据{ car_id: 12345, basic_info: { brand: 宝马, series: 5系, model: 530Li 尊享型, year: 2023款 }, specs: { 车身: { 长度(mm): 4963, 轴距(mm): 2975 }, 发动机: { 排量(L): 2.0, 最大功率(kW): 185 } }, source: autohome, update_time: ISODate(2023-05-20T08:00:00Z) }5.2 高性能写入实现MongoDB的批量写入和异步机制可最大化写入吞吐量from pymongo import MongoClient, InsertOne def save_to_mongodb(data_list, collection_name): client MongoClient(mongodb://localhost:27017/) db client[car_data] collection db[collection_name] # 构建批量操作请求 operations [InsertOne(doc) for doc in data_list] # 批量写入设置orderedFalse实现并行插入 try: result collection.bulk_write(operations, orderedFalse) print(f插入数量: {result.inserted_count}) except BulkWriteError as bwe: print(f部分写入失败: {bwe.details})性能优化技巧合理设置writeConcern级别平衡安全性与性能对于日志类数据可考虑unacknowledged写入使用投影优化查询只返回必要字段对常用查询条件建立适当索引6. 混合存储架构结合两者优势在实际生产环境中我们可以采用混合架构发挥各自优势元数据管理使用MySQL存储品牌、车系等结构化元数据参数详情使用MongoDB存储车型详细配置参数缓存层Redis缓存热点数据和去重集合数据同步方案def sync_hybrid_data(car_data): # MySQL存储基础信息 mysql_data { car_id: car_data[car_id], brand: car_data[basic_info][brand], model: car_data[basic_info][model] } save_to_mysql([mysql_data], car_basic) # MongoDB存储完整数据 save_to_mongodb([car_data], car_details) # Redis更新缓存 r redis.Redis() r.hset(fcar:{car_data[car_id]}, mapping{ brand: car_data[basic_info][brand], model: car_data[basic_info][model] })这种架构既保证了核心业务数据的ACID特性又为灵活的参数数据提供了可扩展的存储方案。