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

做者:xiaoyu
微信公众号:Python数据科学
知乎:Python数据分析师正则表达式


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

网页结构分析

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

clipboard.png

每页的住房信息:

clipboard.png

点开连接后的详细信息:

clipboard.png

博主并无采用分区域进行爬取,博主是直接进行所有爬取,而后循环下一页完成的。步骤很简单,以下:数据结构

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

Scrapy代码实现

数据结构定义

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

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,表明生成器。scrapy

  • 第一个yield返回每一页的下一页连接next_pageurl
  • 第二个yield返回每一页全部的住房详细连接,并再次Request请求跟进,而后调用下一个回调函数parse_detail

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

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住房信息,并返回载有信息的itemide

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中进行简单的清理工做,使用正则表达式实现,代码以下:函数

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参数。学习

ITEM_PIPELINES = {
   'anjuke.pipelines.AnjukePipeline': 300,
}

命令行运行

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

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

scrapy crawl anjuke -o items.csv

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

开始进行爬取:

clipboard.png

数据可视化分析

爬取数据后,咱们获得了一个csv文件,打开显示以下:

clipboard.png

而后,咱们将使用jupyter notebook进行数据分析,代码以下:

clipboard.png

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

效果图以下:

clipboard.png

clipboard.png

总结

本篇只是一个简单的例子,一个完整的高效的爬虫还有不少须要完善。

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

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


关注微信公众号Python数据科学,获取 120G 人工智能 学习资料。

图片描述
图片描述

相关文章
相关标签/搜索