代码编织梦想

一、背景
1、目的: 爬取【某车之家】全部车型数据,用于车贷业务系统的车型选项。
2、结果:
(1)数据内容:共43401条数据,包括【某车之家】全部在售(即将销售)及停售车型;

在这里插入图片描述
(2)数据结构
在这里插入图片描述

二、说明
1、通过requests&BeautifulSoup爬取成功,但耗时较长(约3.5小时),且中途有断掉
2、Scrapy框架爬取不成功,待解决;【请大神们帮助解决】

三、成果(含代码)
1、网页结构
在这里插入图片描述
2、爬取思路
在这里插入图片描述

3、代码【贡献已有成果】
备注:代码中的url有关键字用XXX代替

import requests
from bs4 import BeautifulSoup
import json
import re
import openpyxl

class Cars():
    #【初始函数:获取目录树】:目录树包含了【品牌-厂商-车系-车型】的多层结构
    def __init__(self):
        self.headers={'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'}
        url_tree='https://car.XXX.com.cn/javascript/NewSpecCompare.js?20131010'
        rs_tree=requests.get(url_tree,headers=self.headers)
        rs_tree.encoding='gbk'
        content=rs_tree.text
        self.menu=content.replace('var listCompare$100= ', '').replace(';', '')       
        self.JS=json.loads(self.menu)
        print(self.menu)
    #运行结果:(非完整)
    #[{"I":279,"N":"领克","L":"L","List":[{"I":463,"N":"领克","List":[{"I":4221,"N":"领克01"},{"I":4840,"N":"领克01新能源"},{"I":4616,"N":"领克02"},{"I":5014,"N":"领克02新能源"},{"I":4402,"N":"领克03"},{"I":5113,"N":"领克03新能源"},{"I":5194,"N":"领克05"},{"I":5555,"N":"领克06"},{"I":5557,"N":"领克06新能源"}]}]}]
   
     
    #【主函数:遍历目录树】
    def Main(self):
        for i in self.JS:
            self.bid=i['I']
            self.Brand=i['N']
            self.Brand_id='b'+str(self.bid)
            for a in i['List']:
                self.aid=a['I']
                self.Auto=a['N']
                self.Auto_id='fct_'+str(self.aid)
                for b in a['List']:
                    self.sid=b['I']
                    self.Series=b['N']
                    self.Series_id='series_'+str(self.sid)
                    self.tid='1'
                    self.cid='110100' 
                    self.SSeries() #车系函数
                    self.Price() #车型函数-价格
                    self.Model_sale() #车型函数-在售
                    self.Model_pre_sale() #车型函数-即将销售
                    self.Model_halt() #车型函数-停售
                    self.Result() #结果函数-合并及存储
    
    
    #【车系函数:提取品牌、厂商、车系】
    def SSeries(self):       
        self.brand_list=[]
        self.brand_list.append(str(self.Brand_id))
        self.brand_list.append(self.Brand)
        self.brand_list.append(str(self.Auto_id))
        self.brand_list.append(self.Auto)
        self.brand_list.append(str(self.Series_id))
        self.brand_list.append(self.Series)
        print('【品牌厂商车系】-------------------------------------------------------------------')
        print(self.brand_list)
    #运行结果:['b279', '领克', 'fct_463', '领克', 'series_4221', '领克01']
    
    
    #【车型函数C:单独提取在售车型销售价】                
    def Price(self):
        real_url_4='https://carif.api.XXX.com.cn/dealer/LoadDealerPrice.ashx?'
        params4={
        '_callback': 'LoadDealerPrice',
        'type': self.tid,
        'seriesid': str(self.sid),
        'city': self.cid 
        }
        rs4=requests.get(real_url_4,headers=self.headers,params=params4)
        rs4.encoding='gbk'
        js=json.loads(re.match(".*?({.*}).*",rs4.text,re.S).group(1))
        self.price_dic={}
        prices=js['body']['item']
        for price in prices:
            K=str(price['SpecId'])
            V=round(price['Price']/10000,2)
            Value_price=str(V)+'万元'
            self.price_dic[K]=Value_price
        print('【销售价】----------')
        print(self.price_dic)
    #运行结果:(非完整)
    #{'38980': '16.88万元', '38982': '19.18万元', '38977': '14.98万元', '38981': '17.28万元', '43004': '17.58万元', '46007': '15.18万元', '48423': '19.98万元', '48975': '17.98万元', '38978': '15.88万元', '48424': '20.18万元', '48976': '18.38万元', '38976': '14.38万元'}
    
    
    #【车型函数A:提取在售车型信息】
    def Model_sale(self):
        real_url_2='https://car.XXX.com.cn/price/series-'+str(self.sid)+'.html'
        rs2=requests.get(real_url_2,headers=self.headers)
        print('///在售码///'+str(rs2.status_code))
        rs2.encoding='gbk'
        bs2=BeautifulSoup(rs2.text,'html.parser')
        S=bs2.find('div',class_='tab-nav border-t-no').find_all('li')[0]['class']
        if S[0] != 'disabled':
            self.car_list_2=[]
            sale_status='在售'
            A=bs2.find('div',id='divSeries') 
            lines=A.find_all('li') #车型列表
            for line in lines:
                list_temp=[]
                Model_id=line.find('div',class_='interval01-list-cars').find('p')['id'] #车型编号
                list_temp.append(Model_id)
                Model=line.find('div',class_='interval01-list-cars').find('p').find('a').text #车型
                list_temp.append(Model)
                Configuration=line.find('div',class_='interval01-list-cars').find_all('p')[2].text #配置
                list_temp.append(Configuration)
                Guid_price=line.find('div',class_='interval01-list-guidance').find('div').text #指导价
                list_temp.append(Guid_price)
                if self.price_dic: 
                    key_li=[]
                    for key in self.price_dic:
                        key_li.append(key)
                    if Model_id[1:] in key_li:
                        for keyy in self.price_dic:
                            if keyy==Model_id[1:]:
                                Sale_price=self.price_dic[keyy]
                            else:
                                continue
                    else:
                        Sale_price='暂无报价'
                else:
                    Sale_price='暂无报价'
                list_temp.append(Sale_price)
                list_temp.append(sale_status)
                self.car_list_2.append(list_temp)
            print('【在售车型】---------------------------------------------------------------')
            print(self.car_list_2)
        else:
            self.car_list_2=[]
            print('【在售车型】--------------------------------------------------------------')
            print(self.car_list_2)
    #运行结果:(非完整)
    #[['p48975', '2021款 2.0TD 两驱型Pro', '前置前驱8挡手自一体', ' 17.98万', '17.98万元', '在售'], ['p48976', '2021款 2.0TD 两驱耀Pro', '前置前驱8挡手自一体', ' 18.38万', '18.38万元', '在售'], ['p48423', '2021款 2.0TD 四驱劲Halo', '前置四驱8挡手自一体', ' 19.98万', '19.98万元', '在售']]
    
    
    #【车型函数D:提取即将销售车型信息】
    def Model_pre_sale(self):
        real_url_5='https://car.XXX.com.cn/price/series-'+str(self.sid)+'-0-2-0-0-0-0-1.html'
        rs5=requests.get(real_url_5,headers=self.headers)
        print('///即将销售码'+str(rs5.status_code))
        rs5.encoding='gbk'
        bs5=BeautifulSoup(rs5.text,'html.parser')
        self.car_list_5=[]
        Pre_sale_status='即将销售'
        A=bs5.find('div',id='divSeries') 
        lines=A.find_all('li') #车型列表
        for line in lines:
            list_temp=[]
            Model_id=line.find('div',class_='interval01-list-cars').find('p')['id'] #车型编号
            list_temp.append(Model_id)
            Model=line.find('div',class_='interval01-list-cars').find('p').find('a').text #车型
            list_temp.append(Model)
            Configuration=line.find('div',class_='interval01-list-cars').find_all('p')[2].text #配置
            list_temp.append(Configuration)
            Guid_price=line.find('div',class_='interval01-list-guidance').find('div').text #指导价
            list_temp.append(Guid_price)
            if self.price_dic:
                key_li=[]
                for key in self.price_dic:
                    key_li.append(key)
                if Model_id[1:] in key_li:
                    for keyy in self.price_dic:
                        if keyy==Model_id[1:]:
                            Pre_sale_price=self.price_dic[keyy]
                        else:
                            continue
                else:
                    Pre_sale_price='暂无报价'
            else:
                Pre_sale_price='暂无报价'
            list_temp.append(Pre_sale_price)
            list_temp.append(Pre_sale_status)
            self.car_list_5.append(list_temp)
        print('【即将销售车型】--------------------------------------------------------------------')
        print(self.car_list_5)
    #运行结果:与Model_sale结构相同   
   
     
    #【车型函数B:提取停售车型信息】
    def Model_halt(self):
        self.car_list_3=[]
        real_url_3='https://car.XXX.com.cn/price/series-'+str(self.sid)+'-0-3-0-0-0-0-1.html'
        rs3=requests.get(real_url_3,headers=self.headers)
        print('///停售码'+str(rs3.status_code))
        rs3.encoding='gbk'
        bs3=BeautifulSoup(rs3.text,'html.parser')
        J=bs3.find('div',class_='price-page02')
        if J is None:
            L=2
        else:
            L=17
        for z in range(1,L):
            real_url_3_2='https://car.XXX.com.cn/price/series-'+str(self.sid)+'-0-3-0-0-0-0-'+str(z)+'.html'
            rs3_2=requests.get(real_url_3_2,headers=self.headers)
            rs3_2.encoding='gbk'
            bs3_2=BeautifulSoup(rs3_2.text,'html.parser')
            sale_status='停售'
            A=bs3_2.find('div',id='divSeries')
            lines=A.find_all('li') #车型列表
            for line in lines:
                list_temp=[]
                Model_id=line.find('div',class_='interval01-list-cars').find('p')['id'] #车型编号
                list_temp.append(Model_id)
                Model=line.find('div',class_='interval01-list-cars').find('p').find('a').text #车型
                list_temp.append(Model)
                Configuration=line.find('div',class_='interval01-list-cars').find_all('p')[2].text #配置
                list_temp.append(Configuration)
                Guid_price=line.find('div',class_='interval01-list-guidance').find('div').text #指导价
                list_temp.append(Guid_price)
                Sale_price='待链接'
                list_temp.append(Sale_price)
                list_temp.append(sale_status)
                self.car_list_3.append(list_temp)
        print('【停售车型】------------------------------------------------------------------')
        print(self.car_list_3)
     #运行结果:(非完整)
     #[['p38840', '2019款 2.0T 两驱纯Lite版 国V', '前置前驱6挡手自一体', ' 15.08万 ', '待链接', '停售'], ['p38841', '2019款 2.0T 两驱纯版 国V', '前置前驱6挡手自一体', ' 15.68万 ', '待链接', '停售'], ['p38842', '2019款 2.0T 两驱型版 国V', '前置前驱6挡手自一体', ' 16.58万 ', '待链接', '停售'], ['p38843', '2019款 2.0T 两驱型Pro版 国V', '前置前驱6挡手自一体', ' 17.58万 ', '待链接', '停售']]
    
    
    #【结果函数:数据整理】    
    def Result(self):
        car_list=self.car_list_2+self.car_list_5+self.car_list_3
        lists=[]
        for m in car_list:
            n=self.brand_list+m
            lists.append(n)
        print('【车系列表——存储】')
        print(lists) 
        web=openpyxl.load_workbook(r'D:\Python\Test_file\cars3.xlsx')
        sheetnames=web.get_sheet_names()
        sheet=web.get_sheet_by_name(sheetnames[0])
        sheet=web.active
        nrows=sheet.max_row
        for i in range(1, len(lists)+1):
            for j in range(1, len(lists[i-1])+1):
                sheet.cell(nrows+i, j).value=lists[i-1][j-1]
        web.save(r'D:\Python\Test_file\cars3.xlsx')
    #运行结果:(非完整)
    #[['b279', '领克', 'fct_463', '领克', 'series_5113', '领克03新能源', 'p47091', '2021款 1.5T PHEV', '电动前置前驱7挡双离合', ' 17.67万', '17.67万元', '在售'], ['b279', '领克', 'fct_463', '领克', 'series_5113', '领克03新能源', 'p47092', '2021款 1.5T PHEV Pro', '电动前置前驱7挡双离合', ' 19.67万', '19.67万元', '在售'], ['b279', '领克', 'fct_463', '领克', 'series_5113', '领克03新能源', 'p46416', '2020款 1.5T PHEV Lite', '电动前置前驱7挡双离合', ' 16.87万 ', '待链接', '停售']]
       
DO=Cars()
DO.Main()      

四、问题
问题(一):由于存在以下两种情况,不知道如何设置Scrapy下从[start urls]开始的队列:
(1)、类下的函数存在业务逻辑上的【包含关系】:即“品牌–对应–多个厂商–再对应–多个车系–再对应–多个车型–再对应–多个销售状态‘’。(Scrapy的多url队列为平行执行,如果将车系函数def SSeries(self)、车型函数def Model_sale(self)/def Model_pre_sale(self)/def Model_halt(self)设置为url队列则会失去业务上需要的逻辑对应关系)
在这里插入图片描述

(2) 车型函数(def Model_sale(self) & def Model_pre_sale)需引用价格函数(def Price(self))的输出结果。
在这里插入图片描述
问题(二):爬取的结果数据为列表格式:[[‘b279’, ‘领克’, ‘fct_463’, ‘领克’, ‘series_5113’, ‘领克03新能源’, ‘p47091’, ‘2021款 1.5T PHEV’, ‘电动前置前驱7挡双离合’, ’ 17.67万’, ‘17.67万元’, ‘在售’], [‘b279’, ‘领克’, ‘fct_463’, ‘领克’, ‘series_5113’, ‘领克03新能源’, ‘p47092’, ‘2021款 1.5T PHEV Pro’, ‘电动前置前驱7挡双离合’, ’ 19.67万’, ‘19.67万元’, ‘在售’]],如何通过item传输到pipline中?

请大神们不吝赐教啊!!!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接: https://blog.csdn.net/weixin_45521988/article/details/111088168

day18.用户交互Scanner-爱代码爱编程

用户交互Scanner 今天呢,我们进入基础学习的第二阶段,我们刚学会了语法,但我们还不懂操作,学完这一阶段,我们差不多就可以自己做一些像计算器的小程序了 流程控制 我们这一章要学习流程控制,那我们看看流程控制需要学哪些东西 第一步,我们要学习用户交互的Scanner对象,之前我们学的基本语法只是在IDEA里面输出一下让我们看到,而Scanne

django中如何把时间改为中国时间-爱代码爱编程

方法一: 在setting.py中,修改如下三个参数: LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_TZ = False 即可完成,在使用 DateTimeField 来创建时间时,配置了上边三个参数,保存在数据库的时间就是中国时间。 以下是没有设置上边三个参数和配置的三

Python《使用lxml解析xpath--爬取konachan》-爱代码爱编程

今天尝试使用 lxml 来解析 xpath的文档,其实也就是html文档了啦。 一:lxml和xpath lxml库是一个XML、HTML的解析器,主要用于解析和提取XML、HTML数据。lxml库先将HTML文档解析,然后就可以使用XPath 搜索或遍历HTML文档中的节点。 首先得预先安装lxml,conda install lxml XPath

Python高级编程技巧实战学习_Day13-爱代码爱编程

学习资源传送门:https://www.bilibili.com/video/BV1b5411s76z?p=23 (一)学习内容:如何读写json数据  (二)解决方案   (三)语法解释 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 Python的json模块提供了一种很简单的方式来编码和

深度学习-循环神经网络(RNN)-爱代码爱编程

作者: 明天依旧可好QQ交流群: 807041986 注:关于深度学习的相关问题,若本文未涉及可在下方留言告诉我,我会在文章中进行补充的。 原文链接:https://mtyjkh.blog.csdn.net/article/details/111088248深度学习系列:深度学习(TensorFlow 2)简单入门代码|数据: 微信公众号(明天依旧可好

Python网络爬虫学习笔记(三)正则表达式-爱代码爱编程

正则表达式 正则表达式是处理字符串的强大工具,它有自己特定的语法结构,有了它,实现字符串的检索、替换、匹配验证。 1 实例引入 正则表达式匹配 ,也就是用一定的规则将特定的文本提取出来 。 开源中国提供了正则表达式测试工具: https://tool.oschina.net/regex/ 例子: Hello, my phone number is 01

Python《使用lxml解析xpath--爬取konachan》-爱代码爱编程

今天尝试使用 lxml 来解析 xpath的文档,其实也就是html文档了啦。 一:lxml和xpath lxml库是一个XML、HTML的解析器,主要用于解析和提取XML、HTML数据。lxml库先将HTML文档解析,然后就可以使用XPath 搜索或遍历HTML文档中的节点。 首先得预先安装lxml,conda install lxml XPath

Python《爬虫再练手》-爱代码爱编程

今天发现了一个链接,是GitHub 上有哪些优秀的 Python 爬虫项目? https://www.zhihu.com/question/58151047/answer/859783454 然后呢我大概扫了一眼,挑选了一个网站来搞,没错就是这个http://girl-atlas.net/ 首页就是一个分页了 每一页的地址很有规律,在根地址上增加”

python-CrawlSpider爬取名人名言-爱代码爱编程

爬取名人名言(http://quotes.toscrape.com) import scrapy from scrapy.spiders import CrawlSpider,Rule from scrapy.linkextractors import LinkExtractor class Quotes(CrawlSpider): name

Python网络爬虫学习笔记(三)正则表达式-爱代码爱编程

正则表达式 正则表达式是处理字符串的强大工具,它有自己特定的语法结构,有了它,实现字符串的检索、替换、匹配验证。 1 实例引入 正则表达式匹配 ,也就是用一定的规则将特定的文本提取出来 。 开源中国提供了正则表达式测试工具: https://tool.oschina.net/regex/ 例子: Hello, my phone number is 01

puppeteer爬取数据 await与forEach的问题解决方法-爱代码爱编程

原文:https://www.jb51.cc/python/454296.html 在使用puppeteer爬取数据时,遇到了个报错问题,才发现了这个forEach与await的问题。 一、问题 利用搜集到的url,再去爬去对应数据时,我采用了forEach循环爬取,去遇到提示如下:UnhandledPromiseRejectionWarning: Er

python-CSVfeedSpider 提取csv文件数据-爱代码爱编程

从贵州省数据开放平台下载科技特派员csv文件,文件地址为http://gzopen.oss-cn-guizhou-a.aliyuncs.com/科技特派员.csv 使用命令创建项目>>>scrapy startproject csvfeedspider 进入项目目录>>>cd csvfeedspider >&