在汽车消费决策中,车型参数对比是核心环节。汽车之家作为国内权威汽车资讯平台,汇聚了海量车型的详细参数,但手动整理效率极低。本文将从页面分析、反爬应对、代码实现、数据存储四大维度,手把手教你用 Python 高效爬取汽车之家车型参数对比表,实现数据自动化采集与结构化输出。
一、爬取前的核心准备
1. 技术栈选型
本次爬取采用轻量高效的 Python 技术组合,兼顾开发效率与反爬适配:
- 请求库 :
requests------ 发送 HTTP 请求,模拟浏览器访问 - 解析库 :
BeautifulSoup4------ 解析 HTML 页面,提取参数数据 - 数据处理 :
pandas------ 结构化数据,生成对比表并导出为 CSV/Excel - 反爬工具 :
fake_useragent------ 随机生成 User-Agent,time------ 设置请求延时
安装依赖命令:
bash
运行
pip install requests beautifulsoup4 pandas fake_useragent
2. 页面结构与接口分析
汽车之家车型参数对比采用前后端分离 + 动态渲染架构,核心数据通过 API 接口返回,而非直接嵌入 HTML。
(1)核心接口定位
打开汽车之家车型对比页(如https://car.autohome.com.cn/config/series/45678.html),按 F12 打开开发者工具,切换到「Network」→「XHR」,刷新页面后可定位到参数数据接口:
- 基础参数接口:
https://www.autohome.com.cn/ashx/car/GetConfigNew.ashx?type=base&specid=车型ID - 配置参数接口:
https://www.autohome.com.cn/ashx/car/GetConfigNew.ashx?type=config&specid=车型ID - 车型列表接口:
https://www.autohome.com.cn/ashx/car/getseries.ashx?type=1&value=品牌ID
(2)关键参数说明
specid:车型唯一标识 ID,是获取参数的核心参数type:区分基础参数(base)与配置参数(config)- 响应格式:JSON,包含车型名称、长宽高、动力、安全配置等全量参数
3. 反爬机制与应对策略
汽车之家反爬体系完善,需针对性破解才能稳定爬取:
表格
| 反爬类型 | 表现形式 | 应对方案 |
|---|---|---|
| IP 封禁 | 高频请求触发 403/503 错误 | 代理 IP 轮换、控制请求频率(1-3 秒 / 次) |
| User-Agent 校验 | 无 UA 或异常 UA 被拦截 | 随机 UA 池,模拟真实浏览器标识 |
| 字体反爬 | 价格 / 参数用自定义字体显示为乱码 | 解析字体文件,建立字符映射表 |
| 验证码拦截 | 访问过快弹出图形验证码 | 降低请求频率,必要时接入打码平台 |
二、完整爬取代码实现
1. 基础配置与工具函数
python
运行
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import random
from fake_useragent import UserAgent
# 初始化UA池
ua = UserAgent()
# 请求延时(避免触发反爬)
DELAY = random.uniform(1, 3)
# 基础请求头
BASE_HEADERS = {
"Referer": "https://car.autohome.com.cn/",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "zh-CN,zh;q=0.9",
"Origin": "https://car.autohome.com.cn"
}
# 随机生成请求头
def get_headers():
headers = BASE_HEADERS.copy()
headers["User-Agent"] = ua.random
return headers
# 发送请求(含异常处理)
def send_request(url, retries=3):
for _ in range(retries):
try:
response = requests.get(url, headers=get_headers(), timeout=10)
response.raise_for_status()
return response.json() if "json" in response.headers.get("Content-Type", "") else response.text
except Exception as e:
print(f"请求失败,重试中:{e}")
time.sleep(DELAY)
print(f"请求失败,已达最大重试次数:{url}")
return None
2. 获取车型 ID(核心前置步骤)
车型 ID 是爬取参数的关键,需先从品牌列表页提取:
python
运行
# 获取指定品牌的所有车型ID
def get_model_ids(brand_id):
api_url = f"https://www.autohome.com.cn/ashx/car/getseries.ashx?type=1&value={brand_id}"
data = send_request(api_url)
model_ids = []
if data and data.get("result") and data["result"].get("serieslist"):
for series in data["result"]["serieslist"]:
model_ids.append({
"model_id": series["id"],
"model_name": series["name"],
"brand_name": series["brandname"]
})
return model_ids
# 示例:获取奥迪(品牌ID:3170)的所有车型ID
audi_models = get_model_ids(3170)
print(f"奥迪车型数量:{len(audi_models)}")
3. 爬取车型参数并生成对比表
python
运行
# 爬取单个车型的基础+配置参数
def scrape_model_params(model_id, model_name):
# 基础参数
base_url = f"https://www.autohome.com.cn/ashx/car/GetConfigNew.ashx?type=base&specid={model_id}"
base_data = send_request(base_url)
# 配置参数
config_url = f"https://www.autohome.com.cn/ashx/car/GetConfigNew.ashx?type=config&specid={model_id}"
config_data = send_request(config_url)
if not base_data or not config_data:
return None
# 提取核心参数(可根据需求扩展)
params = {
"车型名称": model_name,
"厂商": base_data.get("carbrand", ""),
"级别": base_data.get("levelname", ""),
"能源类型": base_data.get("fueltypename", ""),
"长*宽*高(mm)": base_data.get("size", ""),
"轴距(mm)": base_data.get("wheelbase", ""),
"发动机型号": base_data.get("enginename", ""),
"最大功率(kW)": base_data.get("maxpower", ""),
"最大扭矩(N·m)": base_data.get("maxtorque", ""),
"变速箱": base_data.get("gearbox", ""),
"驱动方式": base_data.get("drivetype", ""),
"安全配置": "、".join([item["name"] for item in config_data.get("safebag", [])]),
"辅助配置": "、".join([item["name"] for item in config_data.get("assist", [])])
}
return params
# 批量爬取并生成对比表
def generate_comparison_table(brand_models):
all_params = []
for model in brand_models:
print(f"正在爬取:{model['model_name']}")
params = scrape_model_params(model["model_id"], model["model_name"])
if params:
all_params.append(params)
time.sleep(DELAY)
# 生成DataFrame并导出
df = pd.DataFrame(all_params)
df.to_csv("汽车之家车型参数对比表.csv", index=False, encoding="utf_8_sig")
df.to_excel("汽车之家车型参数对比表.xlsx", index=False)
print("参数对比表生成完成!")
return df
# 执行批量爬取
if audi_models:
comparison_df = generate_comparison_table(audi_models)
print(comparison_df.head())
三、代码优化与进阶技巧
1. 代理 IP 集成(应对 IP 封禁)
python
运行
# 代理IP池(示例,实际需使用稳定代理)
PROXY_POOL = [
{"http": "http://112.85.160.10:8080", "https": "http://112.85.160.10:8080"},
{"http": "http://115.223.201.5:3128", "https": "http://115.223.201.5:3128"}
]
# 修改send_request函数,添加代理
def send_request(url, retries=3):
for _ in range(retries):
try:
proxy = random.choice(PROXY_POOL)
response = requests.get(url, headers=get_headers(), proxies=proxy, timeout=10)
response.raise_for_status()
return response.json() if "json" in response.headers.get("Content-Type", "") else response.text
except Exception as e:
print(f"请求失败,重试中:{e}")
time.sleep(DELAY)
return None
2. 字体反爬破解(解决参数乱码)
汽车之家部分参数(如价格)采用自定义字体,需解析字体文件建立映射:
python
运行
import re
from fontTools.ttLib import TTFont
# 解析字体文件,生成字符映射表
def parse_font(font_url):
response = requests.get(font_url, headers=get_headers())
with open("temp.woff", "wb") as f:
f.write(response.content)
font = TTFont("temp.woff")
# 提取字符映射(需根据实际字体调整)
cmap = font.getBestCmap()
char_map = {chr(k): v for k, v in cmap.items() if k > 128}
return char_map
# 替换乱码参数
def replace_garbled(text, char_map):
for garbled, real in char_map.items():
text = text.replace(garbled, real)
return text
3. 增量爬取(避免重复采集)
使用 Redis 存储已爬取的车型 ID,实现增量更新:
python
运行
import redis
# 连接Redis
r = redis.Redis(host="localhost", port=6379, db=0)
# 增量爬取判断
def is_scraped(model_id):
return r.sismember("scraped_model_ids", model_id)
def mark_scraped(model_id):
r.sadd("scraped_model_ids", model_id)
# 修改批量爬取逻辑
def generate_comparison_table(brand_models):
all_params = []
for model in brand_models:
if is_scraped(model["model_id"]):
print(f"{model['model_name']} 已爬取,跳过")
continue
params = scrape_model_params(model["model_id"], model["model_name"])
if params:
all_params.append(params)
mark_scraped(model["model_id"])
time.sleep(DELAY)
# 导出数据...
四、法律与道德规范
爬取数据需遵守以下规则,避免法律风险:
- 遵守
robots.txt协议:汽车之家robots.txt禁止爬取部分敏感页面,需严格遵循 - 控制请求频率:避免高频请求导致服务器压力,设置合理延时
- 数据使用合规:仅用于个人学习、研究,不得用于商业用途或非法传播
- 尊重版权:汽车之家数据受版权保护,爬取后不得擅自二次分发
五、总结
本文通过 Python 实现了汽车之家车型参数对比表的自动化爬取,从接口分析、反爬应对到代码落地,覆盖了完整的爬虫流程。通过代理 IP、字体反爬破解、增量爬取等优化,可实现稳定、高效的数据采集。