深圳链家数据抓取2.0版本

昨天的版本只能爬在售房源,而且到最后和网站数据比,少了几百个,这肯定是哪里出错了啊,像我这种上升处女,受不了啊。

今天重新整理了下思路,从小区信息开始往下爬,一次性把在售房源数据和成交房源数据爬下来,简单粗暴。

新思路

从小区首页开始,获取深圳所有小区,并通过小区页面中在售房源和成交房源的链接,获取每个小区所有的房源。

深圳链家数据抓取2.0版本_第1张图片
思路

以前不知道scrapy怎么同时保存2个以上的item,这次为了能同时存下小区信息,在售房源信息和成交房源信息,特意去学习了下,发现还是挺简单的,在items.py中多创建几个item类,pipelines.py中判断item的类别,采用不同的方式保存数据。

    def process_item(self, item, spider):
        if isinstance(item,XiaoquItem):
            self.db[self.collection_xiaoqu].update({'小区链接':item['小区链接']},dict(item),True)
        elif isinstance(item,ZaishouItem):
            self.db[self.collection_zaishou].update({'房屋链接': item['房屋链接']}, dict(item), True)
        elif isinstance(item,ChengjiaoItem):
            self.db[self.collection_chengjiao].update({'房屋链接': item['房屋链接']}, dict(item), True)
        else:
            pass
        return item

这部分就是新技能了,看起来好简单,实际很实用。

爬虫部分直接放代码了,好多哈,我学爬虫以来没一次性写过这么多行代码,成就感满满~

start_url = 'https://sz.lianjia.com/xiaoqu/'


    def start_requests(self):
        yield scrapy.Request(self.start_url,callback = self.parse_daqu,dont_filter=True)

    def parse_daqu(self,response):
        dists = response.xpath('//div[@data-role="ershoufang"]/div/a/@href').extract()
        for dist in dists:
            url = 'https://sz.lianjia.com'+dist
            yield scrapy.Request(url,self.parse_xiaoqu,dont_filter=True)

    def parse_xiaoqu(self,response):
        page_info = response.xpath('//div[@class="page-box house-lst-page-box"]/@page-data').extract()[0]
        page_dic = json.loads(page_info)
        page_num = page_dic.get('totalPage')
        for i in range(page_num + 1):
            url = response.url + 'pg' + str(i) + '/'
            yield scrapy.Request(url, callback=self.parse_xiaoqu_page, dont_filter=True)

    def parse_xiaoqu_page(self,response):
        xiaoqu_urls = response.xpath('//li[@class="clear xiaoquListItem"]/a/@href').extract()
        for xiaoqu_url in xiaoqu_urls:
            xiaoqu_id = xiaoqu_url.split('/')[-2]
            url = 'https://sz.lianjia.com/xiaoqu/'+xiaoqu_id+'/'
            yield scrapy.Request(url, callback=self.parse_xiaoqu_index, dont_filter=True)

    def parse_xiaoqu_index(self,response):
        item = XiaoquItem()
        xiaoqu = response.xpath('//h1[@class="detailTitle"]/text()').extract()[0]
        xiaoqujunjia = float(response.xpath('//span[@class="xiaoquUnitPrice"]/text()').extract()[0]) if response.xpath(
            '//span[@class="xiaoquUnitPrice"]/text()').extract() else ''
        xiaoquzuobiao = re.findall('resblockPosition:\'(.*?)\'', response.text, re.S)[0] if re.findall(
            'resblockPosition:\'(.*?)\'', response.text, re.S) else ''
        daqu = response.xpath('//div[@class="fl l-txt"]/a[3]/text()').extract()[0].rstrip('小区')
        pianqu = response.xpath('//div[@class="fl l-txt"]/a[4]/text()').extract()[0].rstrip('小区')
        soup = BeautifulSoup(response.text,'lxml')
        xiaoquinfo = [i.text for i in soup.select('div.xiaoquInfo div')]
        xiaoqudetail = {}
        for i in xiaoquinfo:
            key = i[:4]
            data = i[4:]
            xiaoqudetail[key] = data
        xiaoqudetail['小区'] = xiaoqu
        xiaoqudetail['小区均价'] = xiaoqujunjia
        xiaoqudetail['小区坐标'] = xiaoquzuobiao
        xiaoqudetail['小区链接'] = response.url
        xiaoqudetail['大区'] = daqu
        xiaoqudetail['片区'] = pianqu
        for key in item.fields:
            if key in xiaoqudetail.keys() and (xiaoqudetail[key] != '暂无信息' and '暂无数据'):
                    item[key] = xiaoqudetail[key]
            else:
                item[key] = ''
        yield item

        on_sale = response.xpath('//div[@class="goodSellHeader clear"]/a/@href').extract()
        if on_sale:
            yield scrapy.Request(on_sale[0], callback=self.parse_onsale, dont_filter=True)
        else:
            pass

        sold = response.xpath('//div[@id="frameDeal"]/a[@class="btn-large"]/@href').extract()
        if sold:
            yield scrapy.Request(sold[0], callback=self.parse_sold, dont_filter=True)
        else:
            pass

    def parse_onsale(self,response):
        page_info = response.xpath('//div[@class="page-box house-lst-page-box"]/@page-data').extract()[0]
        page_dic = json.loads(page_info)
        page_num = page_dic.get('totalPage')
        for i in range(1, page_num + 1):
            url = response.url + 'pg' + str(i) + '/'
            yield scrapy.Request(url, callback=self.parse_onsale_page, dont_filter=True)

    def parse_sold(self,response):
        page_info = response.xpath('//div[@class="page-box house-lst-page-box"]/@page-data').extract()[0]
        page_dic = json.loads(page_info)
        page_num = page_dic.get('totalPage')
        for i in range(1,page_num+1):
            url = response.url+'pg'+str(i)+'/'
            yield scrapy.Request(url,callback=self.parse_sold_page,dont_filter=True)

    def parse_onsale_page(self,response):
        urls = response.xpath('//ul[@class="sellListContent"]/li/a/@href').extract()
        for url in urls:
            yield scrapy.Request(url,callback=self.onsale_page,dont_filter=True)

    def parse_sold_page(self,response):
        urls = response.xpath('//ul[@class="listContent"]/li/a/@href').extract()
        for url in urls:
            yield scrapy.Request(url,callback=self.sold_page,dont_filter=True)

    def onsale_page(self,response):
        item = ZaishouItem()
        soup = BeautifulSoup(response.text, 'lxml')
        title = soup.select('div.title h1')[0].text
        price = float(soup.select('span.total')[0].text) if soup.select('span.total') else ''
        unitprice = float(soup.select('span.unitPriceValue')[0].text.rstrip('元/平米')) if soup.select(
            'span.unitPriceValue') else ''
        houseID = soup.select('div.houseRecord span.info')[0].text.rstrip('举报') if soup.select(
            'div.houseRecord span.info') else ''
        infos = [i.text.strip() for i in soup.select('div.introContent div.content ul li')]
        info = {}
        for i in infos:
            key = i[:4]
            data = i[4:]
            info[key] = data
        info['标题'] = title
        info['总价'] = price
        info['单价'] = unitprice
        info['链家编号'] = houseID
        info['小区'] = soup.select('div.communityName > span.label')[0].text if soup.select('div.communityName > span.label') else ''
        info['房屋链接'] = response.url
        info['建筑面积'] = float(info['建筑面积'].rstrip('㎡')) if '㎡' in info['建筑面积'] else ''
        info['套内面积'] = float(info['套内面积'].rstrip('㎡')) if '㎡' in info['套内面积'] else ''
        info['挂牌时间'] = datetime.datetime.strptime(info['挂牌时间'],'%Y-%m-%d') if info['挂牌时间'] != '暂无数据' else ''
        info['关注'] = int(soup.select('span#favCount')[0].text)
        info['带看'] = int(soup.select('span#cartCount')[0].text)
        for key in item.fields:
            if key in info.keys() and (info[key] != '暂无信息' and '暂无数据'):
                item[key] = info[key]
            else:
                item[key] = ''
        yield item

    def sold_page(self,response):
        item = ChengjiaoItem()
        soup = BeautifulSoup(response.text, 'lxml')
        title = soup.select('div.house-title')[0].text
        chengjiaoriqi = soup.select('div.house-title > div.wrapper > span')[0].text.split(' ')[0]
        zongjia = float(soup.select('span.dealTotalPrice > i')[0].text)
        danjia = float(soup.select('div.price > b')[0].text)
        daikan = int(soup.select('div.msg > span:nth-of-type(4) > label')[0].text)
        guanzhu = int(soup.select('div.msg > span:nth-of-type(5) > label')[0].text)
        xiaoqu = title.split(' ')[0]
        infos = [i.text.strip() for i in soup.select('div.introContent div.content ul li')]
        info = {}
        for i in infos:
            key = i[:4]
            data = i[4:]
            info[key] = data
        info['标题'] = title
        info['总价'] = zongjia
        info['单价'] = danjia
        info['成交日期'] = chengjiaoriqi
        info['小区'] = xiaoqu
        info['房屋链接'] = response.url
        info['建筑面积'] = float(info['建筑面积'].rstrip('㎡')) if '㎡' in info['建筑面积'] else ''
        info['套内面积'] = float(info['套内面积'].rstrip('㎡')) if '㎡' in info['套内面积'] else ''
        info['挂牌时间'] = datetime.datetime.strptime(info['挂牌时间'], '%Y-%m-%d') if info['挂牌时间'] != '暂无数据' else ''
        info['关注'] = guanzhu
        info['带看'] = daikan
        for key in item.fields:
            if key in info.keys() and (info[key] != '暂无数据' and '暂无信息'):
                item[key] = info[key]
            else:
                item[key] = ''
        yield item
知识点

1、网页解析依然用的xpath和美丽汤结合,怎么方便怎么来。
2、网页上比较结构化的数据,比如

深圳链家数据抓取2.0版本_第2张图片
深圳链家数据抓取2.0版本_第3张图片

这类的可以一次性把所有字段转成词典,就不需要用选择器一个个的挑出来了。词典可以对应item.fields中的key,第一次用都快爽哭了,想想以前不懂事,泪目啊

3、可以建多个item类,一次处理多种数据。

结果

跑完以后,抓下来26300个在售二手房数据

55000个成交二手房数据

成交二手房链接不知道为什么有2000多个404,其实链接都能打开没问题,可还是出现了错误,不过,不管了,任性!

深圳链家数据抓取2.0版本_第4张图片
后续计划

要开始分析了~

号外号外

晚上发现,链家的反爬虫又回来了。。。。

你可能感兴趣的:(深圳链家数据抓取2.0版本)