Scrapy爬取二手房資訊+視覺化資料分析

Python資料科學發表於2019-03-04

作者:xiaoyu

微信公眾號:Python資料科學

知乎:https://zhuanlan.zhihu.com/pypcfx


本篇介紹一個scrapy的實戰爬蟲專案,並對爬取資訊進行簡單的資料分析。目標是北京二手房資訊,下面開始分析。

網頁結構分析

採用安居客網頁資訊作為二手房的資訊來源。直接點選進入二手房資訊的頁面。

Scrapy爬取二手房資訊+視覺化資料分析

每頁的住房資訊:

Scrapy爬取二手房資訊+視覺化資料分析

點開連結後的詳細資訊:

Scrapy爬取二手房資訊+視覺化資料分析

博主並沒有採用分割槽域進行爬取,博主是直接進行全部爬取,然後迴圈下一頁完成的。步驟很簡單,如下:

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

  • 第一個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住房資訊,並返回載有資訊的item

    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

開始進行爬取:

Scrapy爬取二手房資訊+視覺化資料分析

資料視覺化分析

爬取資料後,我們得到了一個csv檔案,開啟顯示如下:

Scrapy爬取二手房資訊+視覺化資料分析

然後,我們將使用jupyter notebook進行資料分析,程式碼如下:

Scrapy爬取二手房資訊+視覺化資料分析

簡單分析一下各大區的每平米二手房單價各大區二手房數量,資料僅為部分,博主沒等資料全部爬取完,僅供參考。當然也可根據實際情況進行更復雜的資料分析和機器學習進行房價預測。

效果圖如下:

Scrapy爬取二手房資訊+視覺化資料分析

Scrapy爬取二手房資訊+視覺化資料分析

##總結 本篇只是一個簡單的例子,一個完整的高效的爬蟲還有很多需要完善。

  • 加入代理ip池
  • scrapd的部署分散式爬蟲
  • 增量式的爬蟲考慮
  • .... 這些將在後續會慢慢進行介紹,完畢。

關注微信公眾號Python資料科學,帶你走進資料的世界。

Scrapy爬取二手房資訊+視覺化資料分析

相關文章