前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Scrapy爬取二手房信息+可视化数据分析

Scrapy爬取二手房信息+可视化数据分析

作者头像
Python数据科学
发布2018-08-06 17:26:54
1.1K0
发布2018-08-06 17:26:54
举报
文章被收录于专栏:Python数据科学

本篇介绍一个scrapy的实战爬虫项目,并对爬取信息进行简单的数据分析。目标是北京二手房信息,下面开始分析。

网页结构分析

采用安居客网页信息作为二手房的信息来源,直接点击进入二手房信息的页面。

每页的住房信息:

点开链接后的详细信息:

博主并没有采用分区域进行爬取,博主是直接进行全部爬取,然后循环下一页完成的。步骤很简单,如下:

  1. 先把每一页的所有二手住房详细链接爬取到
  2. 请求每一个爬取到的详细链接,解析住房信息
  3. 完成所有解析后,请求下一页的链接
  4. 返回步骤一循环,直到返回内容为空

Scrapy代码实现

数据结构定义

Scrapy中的元数据field其实是继承了Python中的字典数据类型,使用起来很方便,博主直接定义了几个住房的信息,如下代码所示。当然还有高级的用法,配合itemloader加入processor,这里只使用简单的定义即可。

代码语言:javascript
复制
class AnjukeItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    price = scrapy.Field()
    mode = scrapy.Field()
    area = scrapy.Field()
    floor = scrapy.Field()
    age = scrapy.Field()
    location = scrapy.Field()
    district = scrapy.Field()
    pass

爬虫解析

  • 定义了一个继承Scrapy自带的爬虫类Spider
  • 然后一个必不可少的东西是name,它贯穿了整个Scrapy的始终,后面会看到它的作用。
  • start_urls是初始请求的url的列表,也可以有多个初始url,这里只有一个。
  • 由于ScrapySpider类中默认使用了Request请求,因此这里选择不覆盖Request,使用默认请求,且请求中调用parse回调函数。
  • 解析部分用Scrapy的高级selector选择器的xpath进行解析。

parse函数请求中有两个yield,代表生成器。

  • 第一个yield返回每一页的下一页链接next_pageurl。
  • 第二个yield返回每一页所有的住房详细链接,并再次Request请求跟进,然后调用下一个回调函数parse_detail

请求的过程中如果速度过快,会要求输入验证码,这里放慢了请求速度,暂不处理验证部分(后续慢慢介绍)。

代码语言:javascript
复制
class AnjukeSpider(scrapy.Spider):
    name = 'anjuke'
    # custom_settings = {
    #     'REDIRECT_ENABLED': False
    # }
    start_urls = ['https://beijing.anjuke.com/sale/']
    def parse(self, response):
        # 验证码处理部分
        pass
        # next page link
        next_url = response.xpath(
            '//*[@id="content"]/div[4]/div[7]/a[7]/@href').extract()[0]
        print('*********' + str(next_url) + '**********')
        if next_url:
            yield scrapy.Request(url=next_url,
                                 callback=self.parse)
        # 爬取每一页的所有房屋链接
        num = len(response.xpath(
            '//*[@id="houselist-mod-new"]/li').extract())
        for i in range(1, num + 1):
            url = response.xpath(
                '//*[@id="houselist-mod-new"]/li[{}]/div[2]/div[1]/a/@href'
                    .format(i)).extract()[0]
            yield scrapy.Request(url, callback=self.parse_detail)

parse_detail回调函数中使用itemloader解析items住房信息,并返回载有信息的item

代码语言:javascript
复制
    def parse_detail(self, response):
        houseinfo = response.xpath('//*[@class="houseInfo-wrap"]')
        if houseinfo:
            l = ItemLoader(AnjukeItem(), houseinfo)
            l.add_xpath('mode', '//div/div[2]/dl[1]/dd/text()')
            l.add_xpath('area', '//div/div[2]/dl[2]/dd/text()')
            l.add_xpath('floor', '//div/div[2]/dl[4]/dd/text()')
            l.add_xpath('age', '//div/div[1]/dl[3]/dd/text()')
            l.add_xpath('price', '//div/div[3]/dl[2]/dd/text()')
            l.add_xpath('location', '//div/div[1]/dl[1]/dd/a/text()')
            l.add_xpath('district', '//div/div[1]/dl[2]/dd/p/a[1]/text()')
            yield l.load_item()

数据清洗

由于爬取后的items数据很乱,有各种\n,\t等符号,因此在pipelines中进行简单的清理工作,使用正则表达式实现,代码如下:

代码语言:javascript
复制
import re
def list2str(value):
    new = ''.join(value).strip()
    return new
class AnjukePipeline(object):
    def process_item(self, item, spider):
        area = item['area']
        price = item['price']
        loc = item['location']
        district = item['district']
        mode = item['mode']
        age = item['age']
        floor = item['floor']
        modes = list2str(mode)
        item['area'] = int(re.findall(r'\d+', list2str(area))[0])
        item['age'] = int(re.findall(r'\d+', list2str(age))[0])
        item['floor'] = list2str(floor)
        item['location'] = list2str(loc)
        item['district'] = list2str(district)
        item['price'] = int(re.findall(r'\d+', list2str(price))[0])
        item['mode'] = modes.replace('\t', '').replace('\n', '')
        return item

别忘记在setting里面设置pipeline参数。

代码语言:javascript
复制
ITEM_PIPELINES = {
   'anjuke.pipelines.AnjukePipeline': 300,
}

命令行运行

我们想要将爬取的数据输出到一个文件中,csv或者json,我们这里输出为csv格式的文件。

Scrapy中只需要一个command指令即可完成,在项目文件下的命令行输入:

代码语言:javascript
复制
scrapy crawl anjuke -o items.csv

命令行中的anjuke就是最开始我们定义的name

开始进行爬取:

数据可视化分析

爬取数据后,我们得到了一个csv文件,打开显示如下:

然后,我们将使用jupyter notebook进行数据分析,代码如下:

简单分析一下各大区的每平米二手房单价和各大区二手房数量,数据仅为部分,博主没等数据全部爬取完,仅供参考。当然也可根据实际情况进行更复杂的数据分析和机器学习进行房价预测。

效果图如下:

总结

本篇只是一个简单的例子,一个完整的高效的爬虫还有很多需要完善。

  • 加入代理ip池
  • scrapd的部署分布式爬虫
  • 增量式的爬虫考虑
  • ....

这些将在后续会慢慢进行介绍,完毕。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-03-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python数据科学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 网页结构分析
  • Scrapy代码实现
  • 数据结构定义
  • 数据可视化分析
  • 总结
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档