汽车之家车型参数对比表爬取

在汽车消费决策中,车型参数对比是核心环节。汽车之家作为国内权威汽车资讯平台,汇聚了海量车型的详细参数,但手动整理效率极低。本文将从页面分析、反爬应对、代码实现、数据存储四大维度,手把手教你用 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)
    # 导出数据...

四、法律与道德规范

爬取数据需遵守以下规则,避免法律风险:

  1. 遵守robots.txt协议:汽车之家robots.txt禁止爬取部分敏感页面,需严格遵循
  2. 控制请求频率:避免高频请求导致服务器压力,设置合理延时
  3. 数据使用合规:仅用于个人学习、研究,不得用于商业用途或非法传播
  4. 尊重版权:汽车之家数据受版权保护,爬取后不得擅自二次分发

五、总结

本文通过 Python 实现了汽车之家车型参数对比表的自动化爬取,从接口分析、反爬应对到代码落地,覆盖了完整的爬虫流程。通过代理 IP、字体反爬破解、增量爬取等优化,可实现稳定、高效的数据采集。

相关推荐
codeJinger2 小时前
【Python】集合
开发语言·python
威联通安全存储2 小时前
严谨性的数字基石:某精密医疗器械企业基于威联通的数据治理实践
运维·数据库·python
计算机徐师兄2 小时前
Python基于Django的汉语文本阅读难度分级系统(附源码,文档说明)
python·机器学习·django·汉语文本阅读难度分级系统·python文本阅读难度分级·文本阅读难度分级系统·汉语文本阅读难度分级
LinuxGeek10242 小时前
从Centos-7迁移和升级到(银河麒麟)Kylin V7的教程
python·centos·kylin
烟锁池塘柳02 小时前
【Anaconda】修改 Conda 环境存储路径的几种方法(详细教程)
python·pycharm·conda
wefly20172 小时前
无需安装的 M3U8 在线播放器,快速实现 HLS 流预览与调试
java·开发语言·python·开发工具
飞Link2 小时前
深度解析:建模动作序列(Action Sequence Modeling)的实战指南
开发语言·python·数据挖掘
明月(Alioo)2 小时前
OpenClaw与ClawHub的关系:当“智能体”遇上“技能商店”
python·ai·agent
喵手2 小时前
Python爬虫实战:VS Code 扩展市场热门榜单“脱壳”实战!
vscode·爬虫·python·爬虫实战·零基础python爬虫教学·vscode扩展市场热门榜单·vs热门榜单数据采集