【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 Alignmentimport 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 responseelse:if num >= 5:print("请求超过5次,退出程序")breakelse:print("请求失败,正在重新请求...")num += 1time.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("该品牌不存在,请重新输入")continueelse: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)breakif __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_nameprint(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 responseelse:if num >= 5:print("请求超过5次,退出程序")breakelse:print("请求失败,正在重新请求...")num += 1time.sleep(1)
def parse_series(band, response):......while True:choice = input(Fore.RED + "\n请输入需要下载的车型id,输入0则下载该品牌全部车型配置:").strip()if choice in series_dict.keys():# 以下为获取配置的逻辑函数# 构建配置页urlseries_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)breakelse:print("输入的车型id不存在,请重新输入。")continueinput("请按任意键关闭程序...")
– 步骤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}")
【总结】
也算是好的开始,虽然懂的还是不多,但是依葫芦画瓢还是画出来了,其他的东西之后再优化,之后应该还要打包成软件给同事用,再研究研究发一篇。
——以上内容仅供学习,请勿用于违法行为,如有涉及侵权等问题,请及时与我联系。
相关文章:
【Python爬虫】获取汽车之家车型配置附代码(2024.10)
参考大哥,感谢大哥:https://blog.csdn.net/weixin_43498642/article/details/136896338 【任务目标】 工作需要想更方便地下载汽车之家某车系配置清单;(垃圾汽车之家不给下载导出表格,配置页叉掉了车系要出来还要重新…...
JVM 加载 class 文件的原理机制
JVM 加载 class 文件的原理机制 JVM(Java虚拟机)是一个可以执行Java字节码的虚拟机。它负责执行Java应用程序和应用程序的扩展,如Java库和框架。 文章目录 JVM 加载 class 文件的原理机制1. JVM1.1 类加载器1.2 魔数1.3 元空间 2. 类加载2.1 …...
NumPy学习第九课:字符串相关函数
前言 各位有没有注意到,NumPy从第八课开始其实基本上都是讲的是NumPy的函数,而且其实就是各种函数的调用,因为NumPy是一个很强大的函数库,这对我们以后再处理项目中遇到的问题时会有很大的帮助。我们将常用的函数进行一个列举&am…...
卷积神经网络(CNNs)在处理光谱特征的序列属性时表现不佳
卷积神经网络(CNNs)在处理光谱签名的序列属性时表现不佳,主要是由于其固有网络架构的局限性。具体原因如下: 局部感受野(Local Receptive Field): CNN 的核心操作是卷积,它利用局部感…...
【IC】MCU的Tick和晶振频率
Tick 是指 MCU 内部时钟的一个周期,通常表示为一个固定的时间间隔。每个 tick 代表一个时间单位,通常以毫秒(ms)或微秒(μs)为单位。Tick 通常由 MCU 的定时器或计时器生成,作为系统时钟的一部分…...
从0到1学习node.js(npm)
文章目录 一、NPM的生产环境与开发环境二、全局安装三、npm安装指定版本的包四、删除包 五、用npm发布一个包六、修改和删除npm包1、修改2、删除 一、NPM的生产环境与开发环境 类型命令补充生产依赖npm i -S uniq-S 等效于 --save -S是默认选项npm i -save uniq包的信息保存在…...
【STM32 Blue Pill编程实例】-OLED显示DS18B20传感器数据
OLED显示DS18B20传感器数据 文章目录 OLED显示DS18B20传感器数据1、DS18B20介绍2、硬件准备及接线3、模块配置3.1 定时器配置3.2 DS18B20传感器配置3.3 OLED的I2C接口配置4、代码实现在本文中,我们将介绍如何将 DS18B20 温度传感器与 STM32 Blue Pill 开发板连接,并使用 HAL …...
STM32 从0开始系统学习3 启动流程
目录 写在前面 速通:做了什么: 分析I:分析2011年的startup文件所作 分析II:分析2017年的startup文件所作 Helps 2011 2017 Reference 写在前面 请各位看官看本篇笔记的时候首先了解一下计算机体系架构,了解基本…...
交换机:端口安全与访问控制指南
为了实现端口安全和访问控制,交换机通常通过以下几种机制和配置来保护网络,防止未经授权的访问和恶意攻击。 01-端口安全 定义及功能 端口安全功能允许管理员限制每个交换机端口可以学习的MAC地址数量。 通过绑定特定的MAC地址到交换机的某一端口上&a…...
【C++ | 数据结构】八大常用排序算法详解
1. 排序的稳定性 排序是我们生活中经常会面对的问题,小朋友站队的时候会按照从矮到高的顺序排列;老师查看上课出勤情况时,会按照学生的学号点名;高考录取时,会按照成绩总分降序依次录取等等。那么对于排序它是如何定义…...
Oracle 第7章:数据完整性约束
在Oracle数据库中,数据完整性是指确保存储在数据库中的数据的正确性和一致性。为了实现这一点,Oracle提供了多种机制来维护数据完整性,包括主键(Primary Key)、外键(Foreign Key)和唯一性约束&a…...
【核心】静态/动态全覆盖路径规划相关技术研究
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、明确覆盖式路径的目标二、静态/动态全覆盖路径规划相关技术研究(1)静态全覆盖路径规划方法一:波前WaveFront 覆盖算法方法二:图形学映射算…...
Java 实现集成 Google 邮箱第三方登录实践
文章目录 前言前期准备配置客户端 ID 和重定向 URL配置 OAuth 权限请求页面 登录流程前端演示代码后端演示代码 总结个人简介 前言 Google OAuth 2.0 是其中一种常见的第三方登录方式,广泛应用于各类网站和应用程序。通过 Google OAuth 2.0,用户可以使用…...
人人都在学的智能体(AI Agent),带你轻松入门!
一、智能体初认知 AI 智能体(英文:AI Agent)究竟是个啥 先讲个故事 想象一下,你有一个特别能干的虚拟助手,我们叫他小明。小明不是普通人,他是一个智能体,就像一个超级版的 Siri 或者小爱同学&…...
如何在Windows环境下开启Kibana的非localhost访问
Kibana是一个开源的分析和可视化平台,用于探索和可视化Elasticsearch数据。默认情况下,Kibana仅允许在本地访问,但通过一些简单的配置更改,你可以允许远程访问。在本文中,我们将介绍如何在Windows环境下开启Kibana的非…...
蓝桥杯 单片机 DS1302和DS18B20
DS1302 时钟 时钟试题 常作为实验室考核内容 控制三个引脚 P17 时钟 P23输入 P13复位 其他已经配置好 寄存器原理 定位地址 0x80地址 固定格式 0x57 5*107*1 57 小时写入格式 不同 首位区分 A上午 P下午 0为24小时制 1为12小时制 写入8小时 0x87 //1000 7 十二小时制 7…...
前端css-媒体查询@media以及常见使用例子
媒体查询(media)介绍 媒体查询(media)是 CSS 中用来针对不同的设备特性(如屏幕尺寸、分辨率等)应用不同样式的一种技术。通过媒体查询,可以使页面在不同设备上呈现不同的布局,实现响…...
centos系统防火墙SELinux设置指令
SELinux(Security-Enhanced Linux)的配置可以通过一系列步骤和命令来完成。以下是一些基本的配置SELinux的方法和步骤: 一、查看SELinux状态 首先,你需要查看SELinux的当前状态。可以使用以下命令: getenforce 该命…...
记录如何在RK3588板子上跑通paddle的OCR模型
官网文档地址 rknn_zoo RKNPU2_SDK RKNN Model Zoo 一、PC电脑是Ubuntu22.04系统中完成环境搭建(板子是20.04) 安装模型转换环境 conda create -n rknn2 python3.10 conda activate rknn2 安装Ubuntu依赖包 su…...
通过AWS Bedrock探索 Claude 的虚拟桌面魔力:让 AI 代替你动手完成任务!
前言 大家好,昨夜Anthropic 发布了更新。现在 Claude 3.5 Sonnet(V2) 和 Claude 3.5 Haiku,以及名为 computer use 的新功能已经作为公开测试版发布了。 Introducing computer use, a new Claude 3.5 Sonnet, and Claude 3.5 Ha…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

