深圳链家数据抓取2.0版本

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

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

新思路

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

思路

以前不知道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、网页上比较结构化的数据,比如

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

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

结果

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

55000个成交二手房数据

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

后续计划

要开始分析了~

号外号外

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容