news 2026/7/5 22:21:47

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 爬虫实战:汽车之家 50,524 条车型数据入库,MySQL 与 MongoDB 性能对比

Python 爬虫实战:汽车之家 50,524 条车型数据入库与数据库选型指南

1. 爬虫数据存储的核心挑战

在数据驱动的互联网时代,爬虫技术已成为获取信息的重要手段。但许多开发者在完成数据抓取后,往往面临一个关键问题:如何高效、可靠地存储这些海量数据?以汽车之家50,524条车型数据为例,我们不仅要考虑存储效率,还需关注后续查询和分析的便捷性。

传统做法是将数据简单写入CSV或文本文件,但当数据量达到数万条甚至更多时,这种方式的局限性就暴露无遗:

  • 数据查询效率低下
  • 缺乏结构化存储能力
  • 难以支持并发读写
  • 数据安全性和完整性无法保障

数据库选型的三个关键维度

  1. 写入性能:爬虫通常需要快速存储大量数据
  2. 查询效率:后续分析需要高效的数据检索
  3. 灵活性:应对可能变化的字段和数据结构

2. 汽车之家爬虫实战:数据抓取与清洗

2.1 目标网站分析与请求构造

汽车之家网站采用传统的HTML结构与动态加载相结合的方式展示车型数据。我们的爬虫需要处理两种主要页面:

  1. 车型列表页:包含品牌、车系和基础车型信息
  2. 车型详情页:包含具体参数配置
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, headers=headers, params=params) 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 = f"https://car.autohome.com.cn/price/brand-{brand_id}.html" response = requests.get(url, headers=headers) 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):约78MB
  • MongoDB:约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`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 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`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

4.2 高效数据写入技巧

使用批量插入和连接池技术显著提升性能:

import pymysql from pymysql import cursors def save_to_mysql(data_list, table_name): conn = pymysql.connect( host='localhost', user='root', password='yourpassword', database='car_data', cursorclass=cursors.DictCursor ) try: with conn.cursor() as cursor: # 构建批量插入SQL keys = data_list[0].keys() sql = f"INSERT 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:i+1000]) 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] # 批量写入,设置ordered=False实现并行插入 try: result = collection.bulk_write(operations, ordered=False) print(f"插入数量: {result.inserted_count}") except BulkWriteError as bwe: print(f"部分写入失败: {bwe.details}")

性能优化技巧

  • 合理设置writeConcern级别平衡安全性与性能
  • 对于日志类数据可考虑unacknowledged写入
  • 使用投影优化查询,只返回必要字段
  • 对常用查询条件建立适当索引

6. 混合存储架构:结合两者优势

在实际生产环境中,我们可以采用混合架构发挥各自优势:

  1. 元数据管理:使用MySQL存储品牌、车系等结构化元数据
  2. 参数详情:使用MongoDB存储车型详细配置参数
  3. 缓存层: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(f"car:{car_data['car_id']}", mapping={ 'brand': car_data['basic_info']['brand'], 'model': car_data['basic_info']['model'] })

这种架构既保证了核心业务数据的ACID特性,又为灵活的参数数据提供了可扩展的存储方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/5 22:18:03

AI驱动的氢氧火焰切割技术解析与应用

1. 项目概述:AI氢氧火焰切割的技术革命在金属加工行业干了十五年,我见证过太多次工人师傅们弯腰调整火焰枪头的场景。传统丙烷切割枪喷出的橙红色火焰总伴随着刺鼻气味,车间里常年弥漫着未完全燃烧的燃气味道。更让人头疼的是,每次…

作者头像 李华
网站建设 2026/7/5 22:17:18

Seedance 2.0鉴权配置12类高危漏洞与安全实践

1. 项目概述:当鉴权成为攻击面最近在帮几个团队做安全审计,发现一个挺普遍但容易被忽视的问题:API密钥管理和动态凭证注入的失效。表面上看,服务跑得好好的,日志里风平浪静,但安全扫描工具一上,…

作者头像 李华
网站建设 2026/7/5 22:17:14

YOLOv1目标检测原理解析与实践指南

1. YOLOv1:单阶段目标检测的开山之作2016年,Joseph Redmon等人在CVPR上发表的《You Only Look Once: Unified, Real-Time Object Detection》彻底改变了目标检测领域的技术路线。作为一名长期从事计算机视觉研究的工程师,我至今记得初次接触Y…

作者头像 李华
网站建设 2026/7/5 22:17:09

Selenium无头模式爬取动态页面实战:以51job招聘数据为例

1. 项目概述:为什么Selenium无头模式是爬取51job这类动态页面的利器最近在帮一个做招聘数据分析的朋友处理数据源,他需要从51job上抓取特定岗位的招聘信息。一开始,他尝试用传统的requests库配合BeautifulSoup,结果发现翻页后列表…

作者头像 李华
网站建设 2026/7/5 22:16:59

SSH双因子认证实战:基于Google Authenticator与PAM模块的安全加固指南

1. 项目概述:为什么SSH需要双因子认证?如果你管理过任何一台暴露在公网的Linux服务器,大概率经历过这样的焦虑:半夜被安全告警吵醒,日志里显示有成千上万次来自未知IP的SSH登录尝试。虽然设置了强密码,甚至…

作者头像 李华
网站建设 2026/7/5 22:14:44

微信好友检测工具WechatRealFriends原理、安全与实操避坑指南

1. 项目概述与核心价值最近在折腾微信数据管理的时候,发现了一个挺有意思的工具,叫WechatRealFriends。这名字直译过来就是“微信真实好友”,说白了,它就是一个帮你检测微信好友状态的工具。你可能也遇到过这种情况:微…

作者头像 李华