Python 爬虫实战 汽车某家(三) 车型
文章目录
- 一、爬取逻辑分析
- 核心
- 二、爬取页面销售状态分析
- 三、爬取页面车型列表分析
- 四、停售分页分析
- 五、指导价和评分爬取
- 1、指导价html片段
- 2、有评分html片段
- 3、无评分html片段
一、爬取逻辑分析
核心
1、将爬取分为爬取流程和内容解析
1)爬取流程控制请求在售、即将销售、停售的请求分发
2) 内容解析负责当前页面的循环解析和分页请求
二、爬取页面销售状态分析
<div class="tab-nav border-t-no"> <!--状态tab、排序--> <div class="brandtab-cont-sort"><a href="/price/series-4741-0-2-0-0-0-0-1.html" class="ma-r15 current">最热门<i class="icon10 icon10-up"></i></a><a href="/price/series-4741-1-2-0-0-0-0-1.html">按价格<span class="icon-cont"><i class="icon10 icon10-sjt"></i><i class="icon10 icon10-sjb"></i></span></a></div><ul data-trigger="click"><li class="disabled"><span title="在售是指官方已经公布售价且正式在国内销售的车型">在售</span></li><li class="current"><a href="/price/series-4741-0-2-0-0-0-0-1.html" data-toggle="tab" data-target="#brandtab-2" rel="nofollow" target="_self" title="即将销售是指近期即将在国内销售的车型">即将销售</a></li><li class="disabled"><span title="停售是指厂商已停产并且经销商处已无新车销售的车型">停售</span></li></ul> </div>
三、爬取页面车型列表分析
<ul class="interval01-list"><li data-value="33885"><div class="interval01-list-cars"><div class="interval01-list-cars-infor"><p id="p33885"><a href="//www.autohome.com.cn/spec/33885/#pvareaid=2042128" target="_blank">2018款 基本型</a></p><p></p><p><span></span><span></span></p></div></div><div class="interval01-list-attention"><div class="attention"><span id="spgzd33885" class="attention-value" style="width:100%"></span> </div></div><div class="interval01-list-guidance"><div><a href="//j.autohome.com.cn/pcplatform/staticpage/loan/index.html?specid=33885&pvareaid=2020994" target="_blank" title="购车费用计算"><i class="icon16 icon16-calendar"></i></a> 16.99万</div></div><div class="interval01-list-lowest"><div><span class="red price-link">暂无报价</span> <a class="js-xj btn btn-mini btn-blue btn-disabled" id="pxj33885" name="pxjs4741" target="_blank">询价</a></div></div><div class="interval01-list-related"><div><span id="spspk33885">口碑</span><a class="fn-hide" target="blank" id="spk33885">口碑</a> <a href="/pic/series-s33885/4741.html#pvareaid=100678" target="_blank">图片</a> <span id="spsps33885">视频</span><a class="fn-hide" target="blank" id="sps33885">视频</a> <span>配置</span> </div></div></li></ul>
四、停售分页分析
<div class="page"><a class="page-item-prev page-disabled" href="javascript:void(0)">上一页</a><a href="javascript:void(0);" class="current">1</a><a href="/price/series-65-0-3-0-0-0-0-2.html">2</a><a href="/price/series-65-0-3-0-0-0-0-3.html">3</a><a href="/price/series-65-0-3-0-0-0-0-4.html">4</a><a href="/price/series-65-0-3-0-0-0-0-5.html">5</a><a href="/price/series-65-0-3-0-0-0-0-6.html">6</a><a class="page-item-next" href="/price/series-65-0-3-0-0-0-0-2.html">下一页</a></div>
五、指导价和评分爬取
由于指导价和评分在车型详情页,因此需要在爬取车型配置的时候更新车型表
1、指导价html片段
<span class="factoryprice">厂商指导价:12.08<em>万元</em></span>
2、有评分html片段
<div class="spec-content"> <div class="koubei-con"> <div class="koubei-left"> <div class="koubei-data"> <span>网友评分:<a href="//k.autohome.com.cn/spec/33409/#pvareaid=3454572" class="scroe">4.28分</a></span> <span>口碑印象:<a href="//k.autohome.com.cn/spec/33409/#pvareaid=3454573" class="count">5人参与评价</a></span> </div> <div class="koubei-tags"> <a href="//k.autohome.com.cn/spec/33409/?summarykey=530800&g#pvareaid=3454574" class="athm-tags athm-tags--blue">油耗满意</a> <a href="//k.autohome.com.cn/spec/33409/?summarykey=457074&g#pvareaid=3454574" class="athm-tags athm-tags--default">胎噪很硬</a> </div> </div> <div class="koubei-right"> <p class="koubei-user"> <span> <a href="javascript:void(0)" id="koubei_user" data-userid="32543097" target="_blank"> </a> <i>发表</i> </span> <span> <b title="2018款 118i 时尚型">2018款 118i 时尚型</b> <i>口碑</i> </span> <span><em>车主已追加口碑</em></span> </p> <p class="koubei-info"> <span>裸车价:<em>15.9万</em></span> <span>购车时间:<em>2018年3月</em></span> <span> 耗 电 量: <em>暂无</em> </span> </p> <p class="koubei-list"> <a href="//k.autohome.com.cn/spec/33409/view_2013088_1.html#pvareaid=3454575"> 【最满意的一点】 1、颜值。这个毋庸置疑,尤其是车头真长,显得整车就没有那么小了,而且蓝色虽然已经烂大街了,不过真的...<i>详细 ></i> </a> </p> </div> </div> </div>
3、无评分html片段
<div class="spec-content"> <!-- 空数据 --> <div class="koubei-blank"> <p>本车型暂无优秀口碑,发表优秀口碑赢丰富好礼</p> <p><a href="//k.autohome.com.cn/form/carinput/add/31960#pvareaid=3454571" class="athm-btn athm-btn--mini athm-btn--blue-outline">发表口碑</a></p> </div> </div>
核心类代码:
import scrapy,pymysql,re
from ..mySqlUtils import MySqlUtils
from ..items import SpecItem,SeriesItem
from ..pipelines import SpecPipeline#请求车系下的车型列表信息,完善
class specSpider(scrapy.Spider):name = "specSpider"https="https:%s"host="https://car.autohome.com.cn%s"count=0ruleId=2 # 爬取策略:1为只爬取数据库中不存在的,2是全部更新chexingIdSet=None #重数据库查出的已爬取的车型id集合# 解析车型列表数据,并保存到数据库def parseSpec(self, response):# 解析seriesParams = response.meta['seriesParams']specList=self.extractSpecItem(response)# 保存到数据库for specItem in specList:yield specItem#当前页面解析完成后判断是否存在分页,若存在分页则继续请求分页链接,再解析到本方法中pageData = response.css(".page")if pageData:#取出nextPagepageList = pageData.xpath("a")nextPage=pageList[len(pageList) - 1].xpath("@href").extract_first()#若存在有效的下一页链接,则继续请求if nextPage.find("java") == -1:pageLink = self.host % nextPagerequest = scrapy.Request(url=pageLink, callback=self.parseSpec)request.meta['seriesParams'] = seriesParams # (品牌ID,车系id)yield request#解析车系车型信息def parse(self, response):seriesItem=SeriesItem()seriesParams=response.meta['seriesParams']#解析车系概要信息seriesData = response.css(".lever-ul").xpath("*")#解析车辆级别lever=seriesData[0].xpath("string(.)").extract_first() #'级\xa0\xa0别:中型SUV'lever=lever.split(":")[1].strip()# 解析指导价minPrice = 0maxPrice = 0seriesDataRight = response.css(".main-lever-right").xpath("*")price = seriesDataRight[0].xpath("span/span/text()").extract_first()if price.find("-") != -1:price = price.rstrip("万")price = price.split("-")minPrice = price[0]maxPrice = price[1]# 解析用户评分userScore = 0userScoreStr = seriesDataRight[1].xpath("string(.)").extract_first()if re.search(r'\d+', userScoreStr) != None:userScore = userScoreStr.split(":")[1]#保存车系概要信息到数据库seriesItem['minMoney']=minPriceseriesItem['maxMoney']=maxPriceseriesItem['score']=userScoreseriesItem['jibie']=leverseriesItem['chexiID']=seriesParams[1]# self.log(seriesItem)yield seriesItem# 解析当前车型页面specList = self.extractSpecItem(response)# self.log(specList)# 保存到数据库for specItem in specList:yield specItem#解析车型概要信息#爬取逻辑:# 1、获取在售、即将销售、停售三种状态# 2、依次判断每个状态是否有值,若有值,则判断当前页面是否为直接进入的# 3、解析当前状态数据# 4、当存在分页时继续请求# 1.1 定义三种链接sellingLink='-1' #在售sellWaitLink='-1' #即将销售sellStopLink='-1' #停售# 1.2 取出三种状态statusData = response.css(".tab-nav.border-t-no")statusList = statusData.xpath("ul/li")for statusItem in statusList:status = statusItem.xpath("a")if status:statusDes=status.xpath("text()").extract_first()link=status.xpath("@href").extract_first()if statusDes == '在售':sellingLink=linkif statusDes == '即将销售':sellWaitLink=linkif statusDes == '停售':sellStopLink=link# self.log("-------------------------->status")statusPrint=(sellingLink,sellWaitLink,sellStopLink)# self.log(statusPrint)# 2.2 判断即将销售状态if sellWaitLink != '-1':#若在售有值则证明不是直接请求过来的,则发起请求,否则就是直接请求过来的直接解析if sellingLink != '-1':#发送请求request = scrapy.Request(url=self.host % sellWaitLink, callback=self.parseSpec)request.meta['seriesParams'] = seriesParams # (品牌ID,车系id)yield request# 2.3 判断停售状态if sellStopLink != '-1':#判断在售状态或即将销售状态是否有值,若有值则证明不是直接请求过来的需要请求后才能解析,若有没有值则直接请求过来的,直接解析即可,if sellingLink != '-1' or sellWaitLink != '-1':#请求链接request = scrapy.Request(url=self.host % sellStopLink, callback=self.parseSpec)request.meta['seriesParams'] = seriesParams # (品牌ID,车系id)yield requestelse:# 判断是否存在分页,若存在则继续请求pageData = response.css(".page")if pageData:# 取出nextPagepageList = pageData.xpath("a")nextPage = pageList[len(pageList) - 1].xpath("@href").extract_first()# 若存在有效的下一页链接,则继续请求if nextPage.find("java") == -1:pageLink = self.host % nextPagerequest = scrapy.Request(url=pageLink, callback=self.parseSpec)request.meta['seriesParams'] = seriesParams # (品牌ID,车系id)yield requestdef start_requests(self):self.chexingIdSet=MySqlUtils.parseToChexingIdSet(MySqlUtils.querySpec())# 读取数据库车系表,获取访问车系车型链接seriesItems = MySqlUtils.querySeriesLink()# seriesItems=["https://car.autohome.com.cn/price/series-4171.html"] # 测试停售# seriesItems=["https://car.autohome.com.cn/price/series-4887.html"] # 测试即将销售 具体车型ID:35775# 从断点处开始爬取waitingCrawlItems = list()for id in SpecPipeline.waitingCrawlSeriesIdSet:for item in seriesItems:if id == item[1]:waitingCrawlItems.append(item)break#waitingCrawItems=MySqlUtils.findChexiInChexiSet(seriesItems,SpecPipeline.waitingCrawlSeriesIdSet)for item in waitingCrawlItems:# 统计已爬取的车系SpecPipeline.crawledSeriesCount += 1SpecPipeline.crawledSeriesIdSet.add(item[1])url=item[2]# url = itemrequest = scrapy.Request(url=url, callback=self.parse)request.meta['seriesParams'] = (item[0], item[1]) # (品牌ID,车系id)# request.meta['seriesParams'] = ('122', '4887') # (品牌ID,车系id)yield request# 封装取出车型集合def extractSpecItem(self,response):# 解析seriesParams = response.meta['seriesParams']specDataGroups = response.css(".interval01-list")specList=list()for specDataGroup in specDataGroups:for specDataItem in specDataGroup.xpath("li"):# 车型idspecId = specDataItem.xpath("@data-value").extract_first()specNameData = specDataItem.css("#p" + specId).xpath("a")# 车型名称specName = specNameData.xpath("text()").extract_first()# 车型链接specLink = self.https % specNameData.xpath("@href").extract_first()specLink=specLink[0:specLink.find("#")-1]specItem = SpecItem()specItem['pinpaiID'] = seriesParams[0]specItem['chexiID'] = seriesParams[1]specItem['chexingID'] = specIdspecItem['name'] = specNamespecItem['url'] = specLinkspecItem['sqlType'] = '1'# self.log(specItem)# 统计新增车型if specId not in self.chexingIdSet:SpecPipeline.addSpecCount += 1# ruleId等于1时只更新新增的车型,已存在的不会做更新if self.ruleId == 1:if specId in self.chexingIdSet:continueself.log("yieldCount:%d" % self.count)# 保存车型到数据库self.count += 1specList.append(specItem)return specList# 批量保存到数据库# def parseSellingSpec(self,response):# print(">>>>>>>>>>>>>>>>>>>>>>>>>>>parseSellingSpec")# t=type(response)# self.log(t)# # 解析# seriesParams = response.meta['seriesParams']# specDataGroups = response.css(".interval01-list")# self.log(seriesParams)# self.log(specDataGroups)# specList=list()# for specDataGroup in specDataGroups:# for specDataItem in specDataGroup.xpath("li"):# # 车型id# specId = specDataItem.xpath("@data-value").extract_first()# specNameData = specDataItem.css("#p" + specId).xpath("a")# # 车型名称# specName = specNameData.xpath("text()").extract_first()# # 车型链接# specLink = self.https % specNameData.xpath("@href").extract_first()# pingpaiID=seriesParams[0]# chexiID=seriesParams[1]# chexingID=specId# specItem=(chexingID,pingpaiID,chexiID,specName,specLink)# specList.append(specItem)# self.log(specItem)# # 保存车型到数据库# self.count += 1# self.log("saveCount:%d" % self.count)# # yield specItem #只有在scrapy.request方法中指定的方法才支持yield# # 使用mysqlUtils将数据保存到数据库# MySqlUtils.insertSpecItemList(specList)# def parseScoreAndPrice(self,response):# #获取传递参数,车型对象# specItem=response.meta['specItem']# #解析评分# scoreData = response.css(".koubei-data")# score=0# if scoreData:# score = scoreData.xpath("span/a")[0].xpath("text()").extract_first()# score = score[0:score.find("分")]# #解析指导价# priceData = response.css(".factoryprice")# price=0# if priceData:# price = priceData.xpath("text()").extract_first()# price=price.split(":")[1]# specItem['money']=price# specItem['score']=score# self.log(specItem)# #将车型信息保存到数据库# yield specItem
Python 爬虫实战 汽车某家(三) 车型相关推荐
- Python 爬虫实战 汽车某家(四) 车型配置
文章目录 一.工具选择 二.demo示例 三.完整代码 前言:汽车之家车型配置数据是js加载+js动态伪元素防爬加载,原始页面中不存在任何数据,因此通过scrapy显式爬取已经不太可能,通过查阅大量资 ...
- Python 爬虫实战 汽车某家(一) 品牌
文章目录 一.品牌爬取 1.进入主页.测试待爬取内容是否为动态加载 2.找到动态请求 3.shell测试请求 附件:异步请求返回的品牌导航栏html 环境: python3.6 scrapy1.5.1 ...
- Python 爬虫实战 汽车某家(五) 口碑、评分
文章目录 一.项目结构 二.核心类代码 爬取内容 1.用户口碑明细评分 2.口碑标题.发表日期.口碑推荐级别 3.购车目的 4.购车价格 5.购车经销商 一.项目结构 point.txt 为断点保存文 ...
- python怎么爬虫理数据_Python神技能 | 使用爬虫获取汽车之家全车型数据
最近想在工作相关的项目上做技术改进,需要全而准的车型数据,寻寻觅觅而不得,所以就只能自己动手丰衣足食,到网上获(窃)得(取)数据了. 汽车之家是大家公认的数据做的比较好的汽车网站,所以就用它吧.(感谢 ...
- python 写csv scrapy_Python神技能 | 使用爬虫获取汽车之家全车型数据
最近想在工作相关的项目上做技术改进,需要全而准的车型数据,寻寻觅觅而不得,所以就只能自己动手丰衣足食,到网上获(窃)得(取)数据了. 汽车之家是大家公认的数据做的比较好的汽车网站,所以就用它吧.(感谢 ...
- python爬虫之汽车之家论坛帖子内容爬取
Datawhale爬虫 第五期 Day7 实战项目:汽车之家车型论坛帖子信息 作为国内目前第一大汽车论坛,反爬虫很恶心,中间很多坑. 新手,第一次搞这么复杂的爬虫,前期没有排查,都是遇到坑的时候再返回 ...
- Python爬取汽车之家所有车型数据,以后买车就用这个参考了
欢迎点击右上角关注小编,除了分享技术文章之外还有很多福利,私信学习资料可以领取包括不限于Python实战演练.大航海计划.BAT内推.学习资料等. 前言 2018年马上就要过去了,经过一年的奋斗,我相 ...
- python爬虫进阶-汽车之家贴吧信息(字体反爬-动态映射)
目的 获取汽车之家贴吧的内容信息 详细需求 汽车之家贴吧 思路解析 一.F12获取目标信息-进行分析 二.字体反爬解析-根据上一篇的文章,直接搜索关键词就好 三 根据其后的链接,保存为ttf在本地,查 ...
- python爬取汽车之家_python爬虫实战之爬取汽车之家网站上的图片
随着生活水平的提高和快节奏生活的发展.汽车开始慢慢成为人们的必需品,浏览各种汽车网站便成为购买合适.喜欢车辆的前提.例如汽车之家网站中就有最新的报价和图片以及汽车的相关内容,是提供信息最快最全的中国汽 ...
最新文章
- NPOI读写Excel
- stl 之 copy copy_backward
- SAP 电商云 Spartacus UI feature level directive 的工作原理
- python网络编程-socket编程
- vue 扫码页面限制区域_Vue.js 单页面多路由区域操作的实例详解
- css背景图片添加url_CSS背景图片–如何向您的Div添加图片URL
- 接口interface修饰符相关问题总结
- 社会内卷的真正原因:华为内部论坛的这篇短文讲透了
- c 语言是一种以解释方式实现的高级语言,高级语言按照计算机执行方式不同可以分为哪两类?它们的执行方式有什么不同,请进行概要说明。...
- python 匿名函数 day15
- 图卷积网络的半监督学习脉络
- ue4手机ui_Epic Games工程师分享:如何在移动平台上做UE4的UI优化?
- numpy.mgrid的用法图解
- C#周立功CAN卡二次开发心得
- qlabel显示两行_PyQt5 系统化学习: QLabel
- Deecamp20 项目提交【如何用pcdet(second)跑自己的数据】
- php类似滴滴系统,除了滴滴顺风车还有哪些顺风车平台好用?
- Redis过期键删除策略
- python实现转置矩阵_用Python转置矩阵?
- 如何实现微信小程序手机号授权
热门文章
- 类人猿学院易语言 yolov7 雷神中控+大漠原生多线程三合一系列教程(最强中控)
- 【每日新闻】就在年底!北京五环内将实现5G信号全覆盖!
- html表单颜色背景图片大全唯美伤感,伤感唯美意境背影图片大全
- 大三Java后端暑期实习面经总结——Java基础篇
- 使用Grafana+Prometheus配置服务器监控
- 怎样看一个PF或LF文件在哪些程序中用到?
- 妙算2配置SiamFC++环境
- 毕业设计 开源物联网系统设计(源码+论文)
- Mysql----复制
- jzoj5399 【NOIP2017提高A组模拟10.7】Confess