【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}")

【总结】

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

架构师备考-背诵精华(计算机语言)

定义 计算机语言是指用于人与计算机之间交流的一种语言&#xff0c;是人与计算机之间传递信息的媒介。计算机语言主要由一套指令组成&#xff0c;而这种指令一般包括&#xff1a;表达式、流程控制和集合三大部分内容。 表达式包括&#xff1a;变量、常量、字面量和运算符流程控…

一个简单的 uas_send_bye.xml for SIPp

<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE scenario SYSTEM "sipp.dtd"> <scenario name"iinv-o200-obye.xml -- wjd 2014"><recv request"INVITE" rrs"true"/><send>&l…

【瑞吉外卖】-day01

目录 前言 第一天项目启动 获取资料 创建项目 ​编辑 连接本地数据库 连接数据库 修改用户名和密码 ​编辑创建表 创建启动类来进行测试 导入前端页面 创建项目所需目录 检查登录功能 登录界面 登录成功 登录失败 代码 退出功能 易错点 前言 尝试一下企业级项…

交叉编译 perl-5.40.0(riscv64)

交叉编译 perl-5.40.0&#xff08;riscv64&#xff09; https://arsv.github.io/perl-cross/usage.html https://github.com/arsv/perl-cross 借助 perl-cross 进行交叉编译 https://www.perl.org/get.html#unix_like 这里获取 perl-5.40.0 的源码 https://github.com/arsv/pe…

时间序列预测(十五)——有关Python项目框架的实例分析

#1024程序员节&#xff5c;征文# 在之前的学习中&#xff0c;已经对时间序列预测的相关内容有了大致的了解。为了进一步加深理解&#xff0c;并能够将所学知识应用于实际中&#xff0c;我决定找一个完整的Python框架来进行深入学习。经过寻找&#xff0c;我终于找到了一篇非常具…

Prometheus+Telegraf实现自定义监控项配置

系列文章目录 运维监控平台搭建 运维监控平台监控标签 golang_Consul代码实现Prometheus监控目标的注册以及动态发现与配置V1版本 Prometheus运维监控平台之监控指标注册到consul脚本开发、自定义监控项采集配置调试(三) golang开发alertmanagerWebhook,实现prometheusalertma…

基于Mysql、JavaScript、PHP、ajax开发的MBTI性格测试网站(前端+后端)

源码地址&#xff1a;https://download.csdn.net/download/2302_79553009/89933699 项目简介 本项目旨在构建一个基于MBTI&#xff08;迈尔斯-布里格斯性格分类指标&#xff09;理论的在线平台——“16Personalities”。该平台利用PHP、MySQL、JavaScript等技术栈开发&#xf…

uniapp的IOS证书申请(测试和正式环境)及UDID配置流程

1.说明 本教程只提供uniapp在ios端的证书文件申请&#xff08;包含正式环境和开发环境&#xff09;、UDID配置说明&#xff0c;请勿用文档中的账号和其他隐私数据进行测试&#xff0c;请勿侵权&#xff01; 2.申请前准备 证书生成网站&#xff1a;苹果应用上传、解析&#x…

202409电子学会青少年机器人技术等级考试(三级)实际操作真题

202409 青少年等级考试机器人实操真题三级 实操试题(共1题&#xff0c;共100分) 1. 主题&#xff1a;亮度可变灯 器件&#xff1a;Atmega328P主控板1块&#xff0c;LED灯模块1个&#xff0c;光敏电阻模块1个及相应辅件。以上模块也可使用分立器件结合面包板搭建。 任务要求&…

【Vispy库】一个用于高性能交互式2D/3D数据可视化库 Python库

Vispy库 1、你好&#xff0c;Vispy&#xff01;2、安装Vispy&#xff0c;轻松上手3、案例一&#xff1a;绘制简单的2D图形4、案例二&#xff1a;3D图形的绘制5、案例三&#xff1a;大规模数据的可视化6、结语 1、你好&#xff0c;Vispy&#xff01; Vispy是一个用于Python的高…

电脑软件下载

开发工具 JDK JDK-23 windowslinuxmac jdk-23_windows-x64_bin.exe jdk-23_linux-x64_bin.tar.gz jdk-23_macos-x64_bin.dmg JDK-21 windowslinuxmac jdk-21_windows-x64_bin.exe jdk-21_linux-x64_bin.tar.gz jdk-21_macos-x64_bin.dmg JDK-17 以下需要登录oracle…

【跨越边界:嵌入式系统在物联网时代的重要性】

摘要 物联网&#xff08;IoT&#xff09;的快速发展正在改变我们的生活方式&#xff0c;而嵌入式系统作为物联网的核心技术之一&#xff0c;其重要性日益凸显。本文将探讨嵌入式系统在物联网中的关键角色&#xff0c;包括其基本概念、应用案例、技术挑战以及未来发展趋势。 1…

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-8

文件下载与邀请翻译者 学习英特尔开发手册&#xff0c;最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册&#xff0c;会是一件耗时费力的工作。如果有愿意和我一起来做这件事的&#xff0c;那么&#xff…

【JavaEE初阶】网络原理—关于TCP协议值滑动窗口与流量控制,进来看看吧!!!

前言 &#x1f31f;&#x1f31f;本期讲解关于TCP协议的重要的机制“连接的建立和断开”~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1…

微信小程序 - 深 / 浅拷贝实现方法,微信小程序深拷贝与浅拷贝,函数方法封装直接调用使用,深拷贝cloneDeep和浅拷贝clone(深复制和浅复制)

前言 在微信小程序中,你无法 直接使用常规浏览器环境中的深浅拷贝方法。 但可以借助 utils.js 实现,下面是方法。 创建深浅拷贝函数 依次打开小程序目录【utils】→【utils.js】,写入深拷贝函数并暴露出去。 // utils.js// 对象深拷贝函数 const deepClone = function(in…

爬虫中Selenium和DrissionPage的区别

运行效率、功能、使用场景 ‌Selenium和DrissionPage在功能、运行效率和适用场景等方面存在显著差异。‌ 功能和运行效率 ‌Selenium‌&#xff1a; ‌功能丰富‌&#xff1a;支持多种编程语言&#xff08;如Python、Java等&#xff09;&#xff0c;与大多数主流浏览器兼容&a…

Docker部署教程:打造流畅的斗地主网页小游戏

Docker部署教程&#xff1a;打造流畅的斗地主网页小游戏 一、项目介绍项目简介项目预览 二、系统要求环境要求环境检查Docker版本检查检查操作系统版本 三、部署斗地主网页小游戏下载镜像创建容器检查容器状态查看容器日志安全设置 四、访问斗地主网页小游戏五、总结 一、项目介…

【Unity】游戏UI中添加粒子特效导致穿层问题的解决

这里介绍一下简易的ui系统中&#xff0c;添加粒子特效导致的穿层问题 首先是在ui界面中添加粒子特效预制体&#xff0c;这个时候&#xff0c;控制这个粒子显示层级的有两个方面 上图中&#xff0c;如果你的Sorting Layer ID的值&#xff08;Layer排序&#xff09;是大于当前C…

以太网交换安全:DHCP Snooping

一、DHCP Snooping的概念及功能 DHCP Snooping是一种用于增强网络中DHCP服务安全性的技术。以下是对以太网交换安全中的DHCP Snooping进行详细的介绍&#xff1a; 基本概述 定义目的&#xff1a;DHCP Snooping是一种网络安全技术&#xff0c;旨在防止未经授权的DHCP服务器在网…

JavaScript中的闭包、递归问题

一、函数定义和调用 1.函数的定义方式 方式一 函数声明方式 function 关键字(命名函数) function fn(){}方式二 函数表达式&#xff08;匿名函数&#xff09; var fn function(){}方式三 new Function() var f new Function(a,b,console.log(a b););//语法 var fn new Fu…