Python爬虫——使用 lxml 解析器爬取汽车之家二手车信息
本次爬虫的目标是汽车之家的二手车销售信息,范围是全国,不过很可惜,汽车之家只显示100页信息,每页48条,也就是说最多只能够爬取4800条信息。
由于这次爬虫的主要目的是使用lxml解析器,所以在信息的查找上面完全只会涉及lxml中选择器的用法,虽然lxml可以同时使用CSS选择器和Xpath选择器,但是为了更加突出效果,暂且只使用Xpath。
爬虫老套路,分为3个步骤:
- 分析网页信息构成,找到切入点
- 获取网页,提取有效信息
- 储存信息
网页分析
网页结构分析的一般思路是先找到第一个需要爬取的链接,然后看看后面的链接是以什么方式构成的,进而选择一种方式全量爬取(一般使用循环或者递归的方式)。
找到切入点——第一个 URL
通过查看链接构成的规律很容易可以发现,汽车之家二手车的信息是由很多选择项来构成URL的,比如按照品牌,或者车系价格城市等等,如果选择清空筛选,那就得到了全国二手车信息的URL,这正是我需要的,URL为http://www.che168.com/china/list/。
分析【下一页】链接的构成
第一页的链接很容易得到,然后可以看到,二手车的信息总计只有100页,每页48个信息,也就是总共有4800个信息可以爬取到。
通过点击“下一页”可以直接看到第2页的链接大概是http://www.che168.com/china/a0_0msdgscncgpi1ltocsp2exb1x0/,继续点击下一页,查看第3页、第4页的链接http://www.che168.com/china/a0_0msdgscncgpi1ltocsp3exb1x0/可以看到,规律很明显,每页的链接构成除了页码中的数字不同外,其他部分完全一样。
选择一种构造链接的方法
通过上面的分析,构造所有100页的链接是件很简单的事情,只需要把链接中的数字部分循环替换一下就行了,这就是循环的方式了。这个方式对付这种链接很有规律的URL在适合不过了,具体参考代码:
for i in range(1,101):
url = 'http://www.che168.com/china/a0_0msdgscncgpi1ltocsp{}exb1x0/'.format(i)
不过,为了更好的适应更加多变的URL,我更加倾向于使用递归的方式来爬取下一页的信息。因此本篇爬虫中不适用上面这种循环爬取的方式,转而使用递归爬取。
所谓递归,首先找到一个递归的出口,也就是爬虫的终点。对于这个爬虫,终点就是当爬到第100页的时候就要结束,既然思路明确了,那可以看看第100页与其他页面有什么不同。
提取信息
递归提取下一页链接
通过分析,可以看到1-99页都有一个“下一页”的按钮,而最后一页是没有这个按钮的,这就是出口。只需要设置一个判断就行了:
def get_items(self,url):
html = requests.get(url,headers=self.headers).text
selector = etree.HTML(html)
next_page = selector.xpath('//*[@id="listpagination"]/a[last()]/@href')[0]
next_text = selector.xpath('//*[@id="listpagination"]/a[last()]/text()')[0]
url_list = selector.xpath('//*[@id="viewlist_ul"]/li/a/@href')
for each in url_list:
the_url = 'http://www.che168.com'+each
self.get_infos(the_url)
if next_text == '下一页':
next_url = 'http://www.che168.com/china'+next_page
self.get_items(next_url)
上面这段代码主要包含下面几个步骤:
html = requests.get(url,headers=self.headers).text
这一句是通过requests来获取网页结构,形成标签树。
selector = etree.HTML(html)
next_page = selector.xpath('//*[@id="listpagination"]/a[last()]/@href')[0]
next_text = selector.xpath('//*[@id="listpagination"]/a[last()]/text()')[0]
上面3句的用意是使用lxml解析网页,然后使用xpath选择器找到下一页的链接,同时尝试找到“下一页”这3个字。
每当找到“下一页”这个按钮,就执行if下面的代码,也就是把找到的下一页链接放入函数中去继续执行,这就形成了递归。当然,前面也说过了,只有1-99页是有这个按钮的,所以到了第100页就找不到这3个字了,这里的if判断就会停止执行, 递归也就结束了。
这一段就是递归的判断:
if next_text == '下一页':
next_url = 'http://www.che168.com/china'+next_page
self.get_items(next_url)
提取二手车主页链接
通过查看页面就能看出来,每个页面有48个二手车信息,但是由于页面信息太少了,所以最好再把每个二手车的主页面打开,所以需要先提取到每个二手车的主页面的链接
这段代码就是提取每个页面的所有二手车链接,并且对每个链接执行函数去提取有效信息:
url_list = selector.xpath('//*[@id="viewlist_ul"]/li/a/@href')
for each in url_list:
the_url = 'http://www.che168.com'+each
self.get_infos(the_url)
可以看到,提取页面中二手车信息的代码是封装到了一个函数中,而这个函数需要传入一个参数,那就是相应的二手车主页URL。
提取每个主页的信息
每个主页是一个单独的链接,所以可以写一个函数,传入一个url,然后输出需要提取的信息就行了,具体代码如下:
def get_infos(self,page_url):
dic = {}
html = requests.get(page_url,headers=self.headers).text
selector = etree.HTML(html)
car_info = selector.xpath('//div[@class="car-info"]')
if car_info:
dic['title'] = car_info[0].xpath('//div[@class="car-title"]/h2/text()')[0]
price = car_info[0].xpath('//div[@class="car-price"]/ins/text()')[0]
dic['price'] = price.strip(' ').replace('¥','')
dic['xslc'] = car_info[0].xpath('//div[@class="details"]/ul/li/span/text()')[0]
dic['scsp'] = car_info[0].xpath('//div[@class="details"]/ul/li/span/text()')[1]
dic['dwpl'] = car_info[0].xpath('//div[@class="details"]/ul/li/span/text()')[2]
dic['city'] = car_info[0].xpath('//div[@class="details"]/ul/li/span/text()')[3]
dic['call_num'] = car_info[0].xpath("//a[contains(@class,'btn') and contains(@class,'btn-iphone3')]/text()")[0]
commitment_tag = car_info[0].xpath('//div[@class="commitment-tag"]/ul/li/span/text()')
dic['commitment_tag'] = '/'.join(commitment_tag)
dic['address'] = car_info[0].xpath('//div[@class="car-address"]/text()')[0].strip()
dic['call_man'] = car_info[0].xpath('//div[@class="car-address"]/text()')[-1].strip()
print(dic)
self.coll.insert(dic)
在这段代码中,首先创建一个空的字典,然后为了后续存储信息更加方便,因此把所有的信息都放到一个字典中去。
提取的方式依然是使用xpath选择器,由于有的信息格式不符合之后要保存的格式,所以使用python的基本方法稍微处理了一下。
最后,再保存信息之前,只用print打印一下提取到信息,查看信息的完整性和准确性。
这样,一个爬虫的前2步就已经完成了,剩下一的就是选中一个合适的方式将信息储存起来。数据库是个好工具,mongodb更是一个好数据库,没错,就是你了!
使用数据库保存信息
连接数据库
由于爬虫的信息不需要太明确的关系,主要目的是存储信息,所以数据库的选择上优先选择mongodb,这种非关系型数据库真是最好不过了。
首先需要导入相应的数据库工具库
from pymongo import MongoClient
然后是连接数据库,由于这个爬虫是写到一个AutohomeSpider类中,因此可以在初始化的时候直接链接指定的数据库,并且可以同时创建表格。
具体代码如下:
self.coon = MongoClient('localhost',27017)
self.coll = self.coon['autohome']['Oldcars']
上述代码可以看到,连接了本地mongodb之后,可以直接创建之前不存在的数据库和数据表。
存入信息
mongodb插入信息的方式非常简单,只需要将数据存放到一个字典中,然后使用 insert()
方法就行。
具体插入信息的代码在上面代码中的
self.coll.insert(dic)
也就是每爬取一条信息就存入mongodb中。
最后爬虫结束,可以使用第三方可视化工具查看一下mongodb中存储的数据:
爬虫源码
爬虫比较简单,爬取的信息也没有多大的价值,因此不做后续深入研究,这个爬虫主要是为了介绍lxml解析器和Xpath选择器。
源码:https://github.com/Hopetree/Spiders100/blob/master/autohome.py
Python爬虫——使用 lxml 解析器爬取汽车之家二手车信息的更多相关文章
- Python 爬虫实例(15) 爬取 汽车之家(汽车授权经销商)
有人给我吹牛逼,说汽车之家反爬很厉害,我不服气,所以就爬取了一下这个网址. 本片博客的目的是重点的分析定向爬虫的过程,希望读者能学会爬虫的分析流程. 一:爬虫的目标: 打开汽车之家的链接:https: ...
- Python爬虫初探 - selenium+beautifulsoup4+chromedriver爬取需要登录的网页信息
目标 之前的自动答复机器人需要从一个内部网页上获取的消息用于回复一些问题,但是没有对应的查询api,于是想到了用脚本模拟浏览器访问网站爬取内容返回给用户.详细介绍了第一次探索python爬虫的坑. 准 ...
- Python爬虫学习三------requests+BeautifulSoup爬取简单网页
第一次第一次用MarkDown来写博客,先试试效果吧! 昨天2018俄罗斯世界杯拉开了大幕,作为一个伪球迷,当然也得为世界杯做出一点贡献啦. 于是今天就编写了一个爬虫程序将腾讯新闻下世界杯专题的相关新 ...
- 爬虫学习(二)--爬取360应用市场app信息
欢迎加入python学习交流群 667279387 爬虫学习 爬虫学习(一)-爬取电影天堂下载链接 爬虫学习(二)–爬取360应用市场app信息 代码环境:windows10, python 3.5 ...
- python3 爬取汽车之家所有车型数据操作步骤(更新版)
题记: 互联网上关于使用python3去爬取汽车之家的汽车数据(主要是汽车基本参数,配置参数,颜色参数,内饰参数)的教程已经非常多了,但大体的方案分两种: 1.解析出汽车之家某个车型的网页,然后正则表 ...
- 【python爬虫】一个简单的爬取百家号文章的小爬虫
需求 用"老龄智能"在百度百家号中搜索文章,爬取文章内容和相关信息. 观察网页 红色框框的地方可以选择资讯来源,我这里选择的是百家号,因为百家号聚合了来自多个平台的新闻报道.首先看 ...
- python爬虫实践(二)——爬取张艺谋导演的电影《影》的豆瓣影评并进行简单分析
学了爬虫之后,都只是爬取一些简单的小页面,觉得没意思,所以我现在准备爬取一下豆瓣上张艺谋导演的“影”的短评,存入数据库,并进行简单的分析和数据可视化,因为用到的只是比较多,所以写一篇博客当做笔记. 第 ...
- Python爬虫开源项目代码,爬取微信、淘宝、豆瓣、知乎、新浪微博、QQ、去哪网等 代码整理
作者:SFLYQ 今天为大家整理了32个Python爬虫项目.整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心.所有链接指向GitHub,祝大家玩的愉快 1.WechatSogou [ ...
- 23个Python爬虫开源项目代码:爬取微信、淘宝、豆瓣、知乎、微博等
来源:全球人工智能 作者:SFLYQ 今天为大家整理了23个Python爬虫项目.整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心.所有链接指向GitHub,祝大家玩的愉快 1.Wec ...
随机推荐
- NOIP2018游记(更新完毕)
10.13 初赛 Day -1 考前 这一次的考场从暗♂德华兴改到了长沙市一中,一进去:我一看,考场在哪???这一中比长郡大了好多,而且连指示牌都没有,这时碰见了谢总,谢总告诉我们在第二教学楼.路上还 ...
- 安装部署VMware vSphere 5.5文档 (6-6) 集群和vMotion
部署VMware vSphere 5.5 实施文档 ########################################################################## ...
- 学习Git操作的好资源
网上资源很多,极大的方便了我们学习新东西. 今天找到了几个简单明了的Git教程,用以备录共享. Learn Git Branching http://pcottle.github.io/learnG ...
- 【KTU Programming Camp (Day 3)】Queries
http://codeforces.com/gym/100739/problem/A 按位考虑,每一位建一个线段树. 求出前缀xor和,对前缀xor和建线段树. 线段树上维护区间内的0的个数和1的个数 ...
- C/C++ 之输入输出
因为C++向下兼容C,所以有多种输入输出的方式,cin/cout十分简洁,但个人觉得不如scanf/printf来的强大,而且在做算法题时,后者运行速度也快些. scanf/printf #inclu ...
- Mysql的学习随笔day2
关于输入中文的问题,各种更改完utf8后仍然乱码. 最后找到一种可行的方法:在insert之前,输入 set names 'gbk' 约束保证数据的完整性和一致性.约束分为表级约束和列级约束,前者可以 ...
- 预防Redis缓存穿透、缓存雪崩解决方案
最近面试中遇到redis缓存穿透.缓存雪崩等问题,特意了解下. redis缓存穿透: 缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有.这样就导致用户查询的时候,在缓存中找不到,每次都要去 ...
- Bootstrap_表格
Bootstrap 表格 Bootstrap 提供了一个清晰的创建表格的布局.下表列出了 Bootstrap 支持的一些表格元素: 标签 描述 <table> 为表格添加基础样式. < ...
- Turtelizer 2 provide JTAG Flash programming and debugging of ARM based boards via USB
http://www.ethernut.de/en/hardware/turtelizer/ Introducing Turtelizer 2 Overview Turtelizer 2 had be ...
- jquery easyui combobox设置默认选中第一项
combobox的内容是从后台获取的json, js截取: var data = $('#id').combobox('getData'); $("#id ").combobox( ...