【Python爬虫】获取汽车之家车型配置附代码(2024.10)

参考大哥,感谢大哥:https://blog.csdn.net/weixin_43498642/article/details/136896338

【任务目标】

工作需要想更方便地下载汽车之家某车系配置清单;(垃圾汽车之家不给下载导出表格,配置页叉掉了车系要出来还要重新刷新,懂不懂用户体验)
每一个车系保存为一个Excel表格,表格命名为“品牌名+车系”。
同品牌的配置表保存到以品牌命名的文件夹中。

【实现效果】

在这里插入图片描述

在这里插入图片描述

【难点痛点】

1、(跳过这条发疯)真的好难找参考代码!可恶!找到的这个大哥文章还给锁了,痛失两百多,下头csdn你欠我的用什么还!你有本事后面别把我的锁成vip!
2、第一次爬不知道干啥,源代码找不到表内数据,不知道在哪找,参考大哥代码一步步做,发现数据似乎没有被加密,后面在响应里找到JSON格式的api文档,直接获取数据。
3、多数据在表内换行格式的调整,用’\n’链接多行数据,openpyxl 设置表内换行。

【逻辑整理】

1、在产品库中利用左侧品牌列表接口获取所有品牌车系名称和id值
2、解析各个车系的名称和id值,用于构建请求车系配置的url
3、通过响应页找到配置url,根据要找的车系id值构建url,从而得到配置数据
4、调整格式,导出文件

【代码实现】

根据需要安装第三方库,pip install xxx

from random import random
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
from datetime import time
from colorama import Fore
from openpyxl import load_workbook
from openpyxl.styles import Alignment

import re
import requests
import json
import os
import pandas as pd
import openpyxl

观察最左列车型列表
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

– 步骤1

输入品牌名称,得到该品牌下的所有车系。

def get_band_response(brand_id="0"):
    num = 1  # 用于统计请求次数
    while True:
        headers = {
            "user-agent": UserAgent().random  # 随机获取ua
        }
        url = "https://car.autohome.com.cn/AsLeftMenu/As_LeftListNew.ashx"
        params = {
            "typeId": "1 ",
            "brandId": brand_id,
            "fctId": "0 ",
            "seriesId": "0"
        }
        response = requests.get(url, headers=headers, params=params)
        if response.status_code == 200:
            return response
        else:
            if num >= 5:
                print("请求超过5次,退出程序")
                break
            else:
                print("请求失败,正在重新请求...")
                num += 1
                time.sleep(1)
 
 
def main():
    while True:
        band = input("请输入汽车品牌:").strip()
        response = get_band_response()
        band_pattern = f"<a href=([^>]*?)><i[^>]*?></i>{band}<em>"
        band_info = re.search(band_pattern, response.text)
        if not band_info:
            print("该品牌不存在,请重新输入")
            continue
        else:
            band_href = band_info.group(1)
            band_id = re.findall(r'/price/brand-(\d+).html', band_href)[0]
            print(F"{band} 品牌id为:", band_id)
            resp_brand = get_band_response(brand_id=band_id)
            # 上面得到了品牌页面的响应数据后,即可往下解析出该品牌下的各个车系的名称的id值
            parse_series(band, response=resp_brand)
            break
  
if __name__ == '__main__':
    main()

– 步骤2

解析各个车系的名称和id值,用于构建请求车系配置的url

.(句点)匹配除了换行之外的所有一个字符, .*(点-星)匹配除了换行外的所有字符
“”.join(list)是Python中的一个常用方法,用于将列表中的所有字符串元素连接起来,元素之间不添加任何分隔符
BeautifulSoup 是一个用于解析HTML和XML文档的Python库。它创建了一个解析树,每个节点代表文档中的一个元素、文本或指令。这使得程序可以轻松地访问和操作文档的各个部分。
CSS选择器来查找HTML文档中的元素".current > dl > dd > a" 这个选择器的意思是:选择所有在带有类名 current 的元素内部的 < dl> 元素的直接子元素 < dd> 内的 < a> 标签。
在这里插入图片描述
enumerate 是 Python 的一个内置函数,它用于将一个可迭代对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标。

def parse_series(band, response):
    html = re.findall(r'document.writeln\("(.*)"\)', response.text)
    html = "".join(html)
    soup = BeautifulSoup(html, "html.parser")
    data_list = soup.select(".current > dl > dd > a")
    still_sell = [i for i in data_list if "停售" not in i.get_text(strip=True)]
    stop_sell = [i for i in data_list if "停售" in i.get_text(strip=True)]
    print(
        f"该品牌共找到{len(data_list)}个车型,其中,在售车型共{len(still_sell)}个,已停售车型共{len(stop_sell)}个车型(停售系列车型无配置信息)。")
    print("----------------------------------------------\n在售车型列表如下:\n----------------------------------------------")
    series_dict = {}
    for still_index, still_data in enumerate(still_sell, start=1):
        series_name = still_data.contents[0].text.strip()
        href = still_data.get("href")
        series_id = re.findall(r'/price/series-(\d+).html', href)[0]
        series_dict[series_id] = series_name
        print(f"序号:{still_index}\t车型:{series_name}\t车型id:{series_id}")
        ......

– 步骤3

找到配置页,根据车系id值,构建配置url
在这里插入图片描述
在这里插入图片描述

def get_response(series_id="0"):
    num = 1  # 用于统计请求次数
    while True:
        headers = {
            "user-agent": UserAgent().random  # 随机获取ua
        }
        url = "https://car-web-api.autohome.com.cn/car/param/getParamConf"
        params = {
            "mode": "1",
            "site": "1",
            "seriesid": series_id
        }
        response = requests.get(url, headers=headers, params=params)
        if response.status_code == 200:
            return response
        else:
            if num >= 5:
                print("请求超过5次,退出程序")
                break
            else:
                print("请求失败,正在重新请求...")
                num += 1
                time.sleep(1)
        
def parse_series(band, response):
	......
    while True:
        choice = input(Fore.RED + "\n请输入需要下载的车型id,输入0则下载该品牌全部车型配置:").strip()
        if choice in series_dict.keys():
            # 以下为获取配置的逻辑函数
            # 构建配置页url
            series_name = series_dict[choice]
            series_url = "https://car.autohome.com.cn/config/series/{}.html".format(choice)
            print(Fore.CYAN + f"---正在下载{band}-{series_name},车型id为:{choice},配置链接为:{series_url}")
            # 获取当前车系的响应数据,即配置,此时的配置信息是不完整的,其中的部分数据是隐藏的,需要解密
            response = get_response(choice)
            if "抱歉" in response.text and "暂无相关数据" in response.text:
                print(Fore.RED + "该系列车暂无配置信息")
                
            # 字典格式的配置信息
            resp_dict=json.loads(response.text)
            # 获取多列配置数据
            all_info = get_car_config(resp_dict)
            df = pd.DataFrame(all_info)
            # 根据要求,提取出车系的上市年份,构建文件名
            excel_name = f"{band}_{series_name}.xlsx"
            # 保存到excel文件中
            save_to_excel(all_info, folder=band, filename=excel_name)
            
            break
        else:
            print("输入的车型id不存在,请重新输入。")
            continue
    input("请按任意键关闭程序...")

– 步骤4

将JSON数据格式调整为列表,方面后面转换为dataframe(颜色不重要懒得处理了先)

# 清洗数据
def get_car_config(config_dic):
    # 获取配置项列表
    allconfig = []
    # 初始化itemname列表
    configname_list = []
    # 遍历titlelist数组
    for title in config_dic['result']['titlelist']:
        # 遍历items数组
        for item in title['items']:
            # 提取itemname并添加到列表中
            configname_list.append(item['itemname'])

    allconfig.append(configname_list)
    
    #获取配置数据
    for data in config_dic['result']['datalist']:
        configvalue_list = []
        # 注意多个数据调整格式,颜色数据另外处理
        for valueitem in data['paramconflist']:
            value_list = []
            if valueitem.get('itemname') != '':
                configvalue_list.append(valueitem['itemname'])
            elif not valueitem.get('sublist'):
                configvalue_list.append('-')
            else:
                stri=[]
                for multivalue in valueitem['sublist']:
                    stri.append(multivalue['value'] + multivalue['name'])
                #连成一个文本串,不要列表形式防止多余'[]'
                stro='\n'.join(stri)
                configvalue_list.append(stro)
        allconfig.append(configvalue_list)
        # 颜色之后处理一下再
    return allconfig

– 步骤5

保存数据,修改格式。

def save_to_excel(data, folder, filename):
    if not os.path.exists(folder):
        os.mkdir(folder)
    df = pd.DataFrame(data)
    # df.T是将表格的行和列进行倒置的操作
    excel_path = f"{folder}/{filename}"
    df.T.to_excel(excel_path, index=False, header=False)

    # 使用openpyxl打开Excel文件,修改单元格对齐方式以启用换行
    workbook = load_workbook(excel_path)
    sheet = workbook.active
    
    # 遍历所有单元格,启用换行和垂直居中
    for row in sheet.iter_rows():
        for cell in row:
            cell.alignment = Alignment(wrap_text=True, vertical='center')
    # 设置列宽
    num_columns = df.shape[0]
    for col in range(1, num_columns + 1):
        sheet.column_dimensions[chr(64 + col)].width = 20
    
    # 保存对工作簿的更改
    workbook.save(excel_path)
    
    print(Fore.GREEN + "配置下载完成,保存到文件------> ", f"{folder}/{filename}")

【总结】

也算是好的开始,虽然懂的还是不多,但是依葫芦画瓢还是画出来了,其他的东西之后再优化,之后应该还要打包成软件给同事用,再研究研究发一篇。

——以上内容仅供学习,请勿用于违法行为,如有涉及侵权等问题,请及时与我联系。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/898626.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

提问: 监督学习, 无监督学习, 机器学习, 深度学习的关系? (通义千问2.5的回答)

前言: 以下内容由AI大模型通义千问大模型2.5生成 监督学习, 无监督学习, 机器学习, 深度学习的关系? 监督学习、无监督学习、机器学习和深度学习是人工智能领域的几个重要概念&#xff0c;它们之间存在一定的关系和区别。下面我将详细解释这些概念及其相互之间的关系&#xf…

Unity中使用UnityEvent遇到Bug

UnityEvent绑定过程中&#xff0c;放在Start&#xff08;&#xff09;中绑定会报错&#xff08;通过脚本添加UnityEvent事件脚本&#xff0c;绑定&#xff09; 绑定事件放在OnEnable&#xff08;&#xff09;中不会报错&#xff0c;但是依然不可以立刻添加UnityEvent事件脚本紧…

GeoWebCache1.26调用ArcGIS切片

GeoServer GeoWebCache (osgeo.org) 一、版本需要适配&#xff1a;Geoserver与GeoWebCache、jdk等的版本适配对照 ​ 查看来源 二、准备工作 1、数据&#xff1a;Arcgis标准的切片&#xff0c;通过ArcGIS Server发布的切片文件&#xff0c;注意切片的存储格式为exploded&…

rust入门基础总结

文章目录 前言1、输出格式规范一、占位符相关&#xff08;一&#xff09;{}与{:?} 二、参数替换方式&#xff08;一&#xff09;位置参数&#xff08;二&#xff09;具名参数 三、格式化参数&#xff08;一&#xff09;宽度&#xff08;二&#xff09;对齐&#xff08;三&…

电脑异常情况总结

文章目录 笔记本无症状息屏黑屏 笔记本无症状息屏黑屏 &#x1f34e; 问题描述&#xff1a; 息屏导致黑屏&#xff1b;依次操作计算机--》右键--》管理--》事件查看器--》Windows日志--》系统&#xff1b;从息屏到异常黑屏之间出现了很多错误&#xff0c;如下&#xff1a;事件…

如何区别医疗器械唯一标识(UDI)、医用耗材统一标识码(HCBS)和医保医用耗材编码

医疗器械唯一标识&#xff08;UDI&#xff09;、医用耗材统一标识码&#xff08;HCBS&#xff09;和医保医用耗材编码三种重要标识&#xff0c;在医疗领域发挥着举足轻重的作用。 医疗器械唯一标识UDI码是被比喻成医疗器械产品的“身份证”&#xff08;每个人都有&#xff09;…

「AIGC」n8n AI Agent开源的工作流自动化工具

n8n AI Agent 是一个利用大型语言模型(LLMs)来设计和构建智能体(agents)的工具,这些智能体能够执行一系列复杂的任务,如理解指令、模仿类人推理,以及从用户命令中理解隐含意图。n8n AI Agent 的核心在于构建一系列提示(prompts),使 LLM 能够模拟自主行为。 传送门→ …

鸿蒙软件开发中常见的如何快速自动生成二维码?QRCode组件

QRCode 用于显示单个二维码的组件。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 二维码组件的像素点数量与内容有关&#xff0c;当组件尺寸过小时&#xff0c;可能出现无法展示内容的情况&…

电脑输入账号密码后,屏幕黑屏只有鼠标解决办法

最近办公电脑出现了两次输入密码后,屏幕黑屏之后鼠标能动的问题,只能有手机查一些资料尝试自己解决,具体什么原因导致的暂时还不清楚。解决这个问题大概有两个方案吧&#xff0c;第一次黑屏用的第一个方案&#xff0c;第二次发现第一个方案不好用了就用的第二个方案。 方案一 …

【Python-AI篇】人工智能机器学习

1. 机器学习简介 1.1 机器学习流程 获取数据 SKLEARN数据集查看数据分布数据集分类 数据基本处理 缺省值处理缩小数据范围异常数据处理数据分割类别不平衡数据处理方式 特征工程机器学习(算法) K-近邻算法线性回归线性回归的改进-岭回归逻辑回归(分类)决策树朴素贝叶斯SVMEM算…

创建型模式-----(单例模式)

目录 基本概念 饿汉式&#xff1a; 懒汉式&#xff1a; 上锁双判空版本 std::call_once版本&#xff1a; C11标准后局部静态变量版本&#xff1a; 项目中单例模板的应用 基本概念 单例模式&#xff1a;在程序运行期间只有一份&#xff0c;与程序生存周期一样&#xff0c;…

记一行代码顺序引起的事故

01 前情回顾 在这里跟同学们分享一个前几天在线上遇见的 bug… bug描述&#xff1a;客户端轮询服务端接口获取数据做打字机效果展示&#xff0c;会偶现输出到一半就停止不动了&#xff0c;但是数据还没输出完&#xff08;如下图&#xff0c;到红色部分就卡住了&#xff09;。…

【Axure高保真原型】移动案例

今天和大家分享多个常用的移动案例的原型模板&#xff0c;包括轮盘滑动控制元件移动、页面按钮控制元件移动、鼠标单击控制元件移动、元件跟随鼠标移动、鼠标拖动控制元件移动、键盘方向键控制元件移动&#xff0c;具体效果可以点击下方视频观看或打开下方预览地址查看哦 【原…

虚拟装配解决方案:在虚拟现实中实现移动零件与三维模型碰撞检测

装配过程占产品开发时间和成本的很大一部分。在投入生产前对产品装配进行碰撞检测能够有效的降低因设计疏忽所导致的重复试错所导致的成本增加&#xff0c;并进一步降低设计审核整体流程所需时间。 选择、移动和操作3D模型的各个部分 TechViz多通道软件具有通用零件识别引擎&am…

Core webapi<1>特性 Route、Bind、HttpGet、Consumes、Produces

微软资料 Consumes Produces 让 API 返回 text/json 类型的数据。因为默认情况下&#xff0c;API 返回数据使用 application/json 格式&#xff0c;所以&#xff0c;咱们要改为 text/json&#xff0c;就得用 Produces 特性。

Java最全面试题->Java基础面试题->JavaEE面试题->Web应用服务器面试题

文章目录 Web应用服务器面试题Tomcat是什么?Tomcat缺省端口是多少&#xff0c;如何修改&#xff1f;Tomcat 有那几种Connector 运行模式&#xff1f;什么是Servlet&#xff1f;Servlet请求过程&#xff1f;Tomcat执行流程&#xff1f;Tomcat部署方式?什么是JBoss ?在JBoss 7…

UG NX12.0建模入门笔记:1.1 UG界面编辑

文章目录 一、用户默认设置&#xff1a;修改新建零件时的默认存储路径。二、用户默认设置&#xff1a;修改默认图纸的尺寸单位。三、如何移除不需要的工具栏&#xff1f;四、如何将角色设置成高级&#xff0c;以使用更多的功能&#xff1f;五、如何修改软件背景颜色&#xff1f…

w~自动驾驶合集9

我自己的原文哦~ https://blog.51cto.com/whaosoft/12320882 #自动驾驶数据集全面调研 自动驾驶技术在硬件和深度学习方法的最新进展中迅速发展&#xff0c;并展现出令人期待的性能。高质量的数据集对于开发可靠的自动驾驶算法至关重要。先前的数据集调研试图回顾这些数据集&…

取得六西格玛绿带培训证书有什么用?

六西格玛作为一套科学的管理方法和工具&#xff0c;已被广泛应用于各个行业。而六西格玛绿带培训证书&#xff0c;作为这一体系中的基础认证&#xff0c;不仅是对个人专业能力的认可&#xff0c;更是职业生涯中的一大助力。本文&#xff0c;天行健企业管理咨询公司旨在分享取得…

山东济南杰出思想家颜廷利:升命学说,当今世界前沿哲学思想

颜廷利教授的"升命学说"是一个将现代科技发展与中华传统文化相结合的当今世界前沿哲学教育理论框架&#xff0c;它是在传统哲学基础上的一种目前社会创新性思想体系。为了理解"升命学说"与传统哲学的不同之处&#xff0c;我们可以从以下几个方面来探讨&…