大家好,我是你们的桃子叔叔!今天给大家带来一个超实用的爬虫项目------批量爬取汽车之家全车型外观图,结合 Scrapy 的高效调度和 Selenium 的动态页面交互能力,完美解决汽车之家的动态加载、反爬限制等问题。
不管你是做汽车数据分析、设计参考,还是AI训练数据收集,这个项目都能直接复用!全程从环境搭建到代码解析,再到运行测试,一步步带你吃透 Scrapy+Selenium 的组合玩法,新手也能轻松上手~
一、项目核心目标
- 数据源:汽车之家车型图片库(https://www.autohome.com.cn/cars/)
- 爬取目标:指定车型的所有外观图(含高清大图)
- 核心需求:
- 自动点击「外观」标签,切换到外观图页面
- 识别「x张外观图」按钮,自动展开所有隐藏图片
- 处理懒加载,抓取完整图片列表
- 图片URL转换(缩略图→高清图)
- 结构化保存(图片下载+JSON数据归档,按车型分类)
- 断点续传(记录下载状态,避免重复爬取)
二、技术栈选型
为什么选 Scrapy+Selenium 组合?
- Scrapy:强大的爬虫框架,负责请求调度、数据管道、并发控制,效率拉满
- Selenium:处理动态交互(点击标签、展开图片),解决 Scrapy 无法应对的 JS 渲染问题
- 辅助工具:ChromeDriver(Selenium 浏览器驱动)、re(正则解析URL)、hashlib(图片重命名去重)
三、环境搭建(一步到位)
1. 基础环境
-
Python 版本:3.8~3.12(推荐3.10,兼容性最佳)
-
检查Python环境:
bashpython --version # 输出版本号即正常
2. 安装依赖库
国内用户直接用默认 PyPI 源下载可能较慢,推荐使用清华镜像源,安装命令如下(复制即可一键安装):
python
# 核心框架+库(清华镜像加速)
pip install scrapy selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
# 辅助工具:自动管理ChromeDriver(无需手动下载)
pip install webdriver-manager -i https://pypi.tuna.tsinghua.edu.cn/simple
# 可选依赖:处理JSON格式化、日志美化(按需安装)
pip install json5 prettytable -i https://pypi.tuna.tsinghua.edu.cn/simple
镜像说明:清华镜像源是国内最稳定的 PyPI 镜像之一,下载速度比默认源快 10~100 倍,支持所有 Python 库。
3. ChromeDriver 配置(关键!)
Selenium 需要 ChromeDriver 才能控制 Chrome 浏览器,提供两种配置方案,按需选择:
方案 1:手动配置(传统方式)
1.查看本地 Chrome 版本(浏览器→设置→关于 Chrome,如 120.0.6099.224)
2.下载对应版本的 ChromeDriver:
- 官方地址:https://sites.google.com/chromium.org/driver/(需科学上网)
- 国内镜像:https://npm.taobao.org/mirrors/chromedriver/(推荐,无需科学上网)
3.配置:将下载的 chromedriver.exe(Windows)或 chromedriver(macOS/Linux)放到 Python 安装目录的 Scripts 文件夹下(如 C:\Python310\Scripts)。
方案 2:自动配置(推荐,用 webdriver-manager)
无需手动下载,通过代码自动匹配 Chrome 版本并下载驱动,修改 car.py 中的驱动初始化逻辑即可:
python
# 替换 car.py 中 Selenium 驱动初始化部分
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
# 初始化 Chrome 浏览器(自动管理驱动)
service = Service(ChromeDriverManager().install()) # 自动下载匹配的ChromeDriver
self.driver = webdriver.Chrome(service=service, options=chrome_options)
优势:无需关注 Chrome 版本,自动适配,避免版本不匹配报错。
4. 验证环境
安装完成后,执行以下命令验证依赖是否正常:
python
# 验证Scrapy
python -m scrapy version # 输出版本号如Scrapy 2.13.4即正常
# 验证Selenium+webdriver-manager
python -c "from selenium import webdriver; from webdriver_manager.chrome import ChromeDriverManager; driver = webdriver.Chrome(ChromeDriverManager().install()); driver.quit(); print('环境正常')"
若输出**「环境正常」**,说明所有依赖配置成功。
四、json数据准备
docs目录文件创建(输入数据准备)
1、car_ids.json:原始车型ID数据
从汽车之家接口获取,步骤如下:
- 打开汽车之家价格页:https://www.autohome.com.cn/price#pvareaid=6861598
- 右键→检查→切换到「Network」(网络)面板;
- 刷新页面,在搜索框输入「treeMenu?extendseries=1」,找到该接口;
- 点击接口→切换到「Preview」(预览)→复制「result」对应的数组(右键→Copy value);
- 在
docs目录下创建car_ids.json文件,将复制的数组粘贴进去(确保格式为JSON数组)。
2、parse_list.py:ID解析脚本
在 docs 目录下创建 parse_list.py,用于将 car_ids.json 解析为格式化的 parsed_cars.json:
python
import json
import os
def parse_car_data(input_file: str = "car_ids.json", output_file: str = "parsed_cars.json"):
# 检查输入文件是否存在
if not os.path.exists(input_file):
print(f" 未找到输入文件:{input_file}")
return []
# 读取原始数据
try:
with open(input_file, 'r', encoding='utf-8') as f:
data = json.load(f)
print(f"成功读取原始数据,共 {len(data)} 个首字母分组")
except json.JSONDecodeError:
print(f"输入文件格式错误,不是有效的JSON")
return []
except Exception as e:
print(f"读取输入文件失败:{str(e)}")
return []
result = []
# 遍历数据结构:首字母分组 → 品牌 → 厂商 → 车系
for letter_group in data:
brand_items = letter_group.get('branditems', [])
for brand_item in brand_items:
brand_name = brand_item.get('name', '未知品牌')
fct_items = brand_item.get('fctitems', [])
for fct_item in fct_items:
series_items = fct_item.get('seriesitems', [])
for series_item in series_items:
# state=20 表示车型有效(根据接口返回规律)
if series_item.get('state', 0) == 20:
car_info = {
'brand': brand_name,
'name': series_item.get('name', '未知车型'),
'id': series_item.get('id', 0),
'download': False # 下载状态标记(断点续传关键)
}
result.append(car_info)
# 去重(避免重复车型)
unique_result = []
car_ids = set()
for car in result:
car_id = car.get('id')
if car_id not in car_ids and car_id != 0:
car_ids.add(car_id)
unique_result.append(car)
# 保存到输出文件
try:
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(unique_result, f, ensure_ascii=False, indent=2)
print(f"解析完成!共提取 {len(unique_result)} 个有效车型,已保存到:{output_file}")
return unique_result
except Exception as e:
print(f"保存输出文件失败:{str(e)}")
return []
if __name__ == "__main__":
# 执行解析(默认读取car_ids.json,输出parsed_cars.json)
parse_car_data()
3、生成parsed_cars.json
在 docs 目录下执行以下命令,生成格式化的车型数据文件:
bash
# 进入docs目录
cd docs
# 执行解析脚本
python parse_list.py
- 执行成功后,
docs目录下会生成parsed_cars.json,包含品牌、车型名称、车型ID和下载状态,格式如下:
json
[
{
"brand": "AITO 问界",
"name": "问界M5",
"id": 6388,
"download": false
},
{
"brand": "AITO 问界",
"name": "问界M7",
"id": 6643,
"download": false
}
]
五、项目结构解析(完整目录+文件说明)
项目构建完成后,目录结构如下(标注了每个文件/目录的作用和创建方式):
carsfetch/ # 项目根目录(执行startproject命令生成)
├── carsfetch/ # 项目核心目录(自动生成)
│ ├── __init__.py # 空文件,标识该目录为Python包(自动生成)
│ ├── items.py # 数据模型定义(自动生成,需修改)
│ ├── middlewares.py # 下载中间件(自动生成,本项目未自定义)
│ ├── pipelines.py # 数据处理管道(自动生成,需修改)
│ ├── settings.py # 项目配置(自动生成,需修改)
│ └── spiders/ # 爬虫核心目录(自动生成)
│ ├── __init__.py # 空文件,标识该目录为Python包(自动生成)
│ └── car.py # 主爬虫文件(执行genspider生成,需大幅修改)
├── docs/ # 输入数据目录(手动创建)
│ ├── car_ids.json # 汽车品牌/车型原始ID数据(手动创建,接口获取)
│ ├── parse_list.py # ID解析脚本(手动创建,用于生成parsed_cars.json)
│ └── parsed_cars.json # 格式化后的车型数据(脚本生成,供爬虫读取)
├── downloaded_images/ # 下载的图片目录(自动生成,按车型分类)
├── output/ # 结构化JSON数据目录(自动生成,按车型分类)
└── scrapy.cfg # Scrapy项目配置文件(自动生成,无需修改)
- 目录说明:
- 自动生成目录/文件:执行
startproject和genspider后自动创建,无需手动干预; - 手动创建目录/文件:
docs目录及内部的car_ids.json、parse_list.py。
- 自动生成目录/文件:执行
接下来我们开始编写核心代码并运行这个项目完成数据爬取
由于字数限制,我把这部分单独放到第二部分中:
爬虫实战|Scrapy+Selenium 批量爬取汽车之家海量车型外观图(附完整源码)二