今天,我们就以链家网南京地区为例,来学习爬取链家网的成交房源数据。

这里推荐使用火狐浏览器,并且安装firebug和firepath两款插件,你会发现,这两款插件会给我们后续的数据提取带来很大的方便。

首先创建一个名称为lianjia的项目。

需求分析

爬取数据的第一步当然是确定我们的需求,大方向就是我们想拿到南京地区的房源成交信息,但是具体的细节信息,我们需要从网页来看,,我们直接在浏览器中输入以下的网址https://nj.lianjia.com/chengjiao/,会显示南京地区的成交的房源信息,包括名称,房屋简介,地理位置,成交日期,成交价格,成交单价等详细信息,这样我们就确定了我们想要的信息,我们在items.py文件中定义如下的一些字段。

  1. #items.py
  2. from scrapy import Item,Field
  3. class LianjiaItem(Item):
  4. region = Field() #行政区域
  5. href = Field() #房源链接
  6. name = Field() #房源名称
  7. style = Field() #房源结构
  8. area = Field() #小区
  9. orientation = Field() #朝向
  10. decoration = Field() #装修
  11. elevator = Field() #电梯
  12. floor = Field() #楼层高度
  13. build_year = Field() #建造时间
  14. sign_time = Field() #签约时间
  15. unit_price = Field() #每平米单价
  16. total_price = Field() #总价
  17. fangchan_class = Field() #房产类型
  18. school = Field() #周边学校
  19. subway = Field() #周边地铁

请注意,以上的信息,并不是每一套房源都有的,比如下面的地铁,学校,很多房源都是没有的。

问题

  • 你会发现一个问题,每一个页面会呈现30条的房源信息,最下面一共可以显示100页,总计最多也就是3000条信息,南京地区的成交房源信息肯定不止这区区的3000条,那么如果直接从这个页面通过翻页来获取数据,最多只能获取到3000条信息,所以我们这里需要转思路。

  • 还是这个页面,可以看到页面上部列出了南京地区的行政区,我们随意选择一个,会发现,新的页面依然是每一页30条,共计100页,但是我们有11个行政区,那么其数量也是翻了好几倍了。

  • 这个时候,你可能还是不满足,我们想办法看一下是不是还可以进一步向下划分,没错那就是小区,我们把房源从11个行政区划分到小区上,以小区为单位,每一个小区上面还有房源数据,这样的话,我们的信息可以说比较全面了,当然了,我们需要做的工作也是要翻倍的。

总结

这里我们通过分析,总结出了如下的思路:

  • 以行政区为单位,先获取南京地区所有的小区信息
  • 以小区为单位,获取每一个小区里面的房源数据
  • 最后就是获取具体的每一个房源的信息。

具体实施

现在明确了我们的思路,下面就开始具体的实施。

编写spider.py文件

  1. from scrapy import Spider,Request
  2. import re
  3. from lxml import etree
  4. import json
  5. from urllib.parse import quote
  6. from lianjia.items import LianjiaItem
  7. class Lianjia_spider(Spider):
  8. name = 'lianjia'
  9. allowed_domains = ['nj.lianjia.com']
  10. regions = {'gulou':'鼓楼',
  11. 'jianye':'建邺',
  12. 'qinhuai':'秦淮',
  13. 'xuanwu':'玄武',
  14. 'yuhuatai':'雨花台',
  15. 'qixia':'栖霞',
  16. 'jiangning':'江宁',
  17. 'liuhe':'六合',
  18. 'pukou':'浦口',
  19. 'lishui':'涟水',
  20. 'gaochun':'高淳'
  21. }
  22. def start_requests(self):
  23. for region in list(self.regions.keys()):
  24. url = "https://nj.lianjia.com/xiaoqu/" + region + "/"
  25. yield Request(url=url, callback=self.parse, meta={'region':region}) #用来获取页码
  26. def parse(self, response):
  27. region = response.meta['region']
  28. selector = etree.HTML(response.text)
  29. sel = selector.xpath("//div[@class='page-box house-lst-page-box']/@page-data")[0] # 返回的是字符串字典
  30. sel = json.loads(sel) # 转化为字典
  31. total_pages = sel.get("totalPage")
  32. for i in range(int(total_pages)):
  33. url_page = "https://nj.lianjia.com/xiaoqu/{}/pg{}/".format(region, str(i + 1))
  34. yield Request(url=url_page, callback=self.parse_xiaoqu, meta={'region':region})
  35. def parse_xiaoqu(self,response):
  36. selector = etree.HTML(response.text)
  37. xiaoqu_list = selector.xpath('//ul[@class="listContent"]//li//div[@class="title"]/a/text()')
  38. for xq_name in xiaoqu_list:
  39. url = "https://nj.lianjia.com/chengjiao/rs" + quote(xq_name) + "/"
  40. yield Request(url=url, callback=self.parse_chengjiao, meta={'xq_name':xq_name,
  41. 'region':response.meta['region']})
  42. def parse_chengjiao(self,response):
  43. xq_name = response.meta['xq_name']
  44. selector = etree.HTML(response.text)
  45. content = selector.xpath("//div[@class='page-box house-lst-page-box']") #有可能为空
  46. total_pages = 0
  47. if len(content):
  48. page_data = json.loads(content[0].xpath('./@page-data')[0])
  49. total_pages = page_data.get("totalPage") # 获取总的页面数量
  50. for i in range(int(total_pages)):
  51. url_page = "https://nj.lianjia.com/chengjiao/pg{}rs{}/".format(str(i+1), quote(xq_name))
  52. yield Request(url=url_page, callback=self.parse_content, meta={'region': response.meta['region']})
  53. def parse_content(self,response):
  54. selector = etree.HTML(response.text)
  55. cj_list = selector.xpath("//ul[@class='listContent']/li")
  56. for cj in cj_list:
  57. item = LianjiaItem()
  58. item['region'] = self.regions.get(response.meta['region'])
  59. href = cj.xpath('./a/@href')
  60. if not len(href):
  61. continue
  62. item['href'] = href[0]
  63. content = cj.xpath('.//div[@class="title"]/a/text()')
  64. if len(content):
  65. content = content[0].split() # 按照空格分割成一个列表
  66. item['name'] = content[0]
  67. item['style'] = content[1]
  68. item['area'] = content[2]
  69. content = cj.xpath('.//div[@class="houseInfo"]/text()')
  70. if len(content):
  71. content = content[0].split('|')
  72. item['orientation'] = content[0]
  73. item['decoration'] = content[1]
  74. if len(content) == 3:
  75. item['elevator'] = content[2]
  76. else:
  77. item['elevator'] = '无'
  78. content = cj.xpath('.//div[@class="positionInfo"]/text()')
  79. if len(content):
  80. content = content[0].split()
  81. item['floor'] = content[0]
  82. if len(content) == 2:
  83. item['build_year'] = content[1]
  84. else:
  85. item['build_year'] = '无'
  86. content = cj.xpath('.//div[@class="dealDate"]/text()')
  87. if len(content):
  88. item['sign_time'] = content[0]
  89. content = cj.xpath('.//div[@class="totalPrice"]/span/text()')
  90. if len(content):
  91. item['total_price'] = content[0]
  92. content = cj.xpath('.//div[@class="unitPrice"]/span/text()')
  93. if len(content):
  94. item['unit_price'] = content[0]
  95. content = cj.xpath('.//span[@class="dealHouseTxt"]/span/text()')
  96. if len(content):
  97. for i in content:
  98. if i.find("房屋满") != -1: # 找到了返回的是非-1得数,找不到的返回的是-1
  99. item['fangchan_class'] = i
  100. elif i.find("号线") != -1:
  101. item['subway'] = i
  102. elif i.find("学") != -1:
  103. item['school'] = i
  104. yield item

我们对上面关键的地方进行解释:

  • start_requests
    这个就是我们以行政区为单位,目的是爬取每一个行政区的小区列表。
  • parse
    对行政区返回的response进行解析,我们目的是拿到这个大的行政区,包含多少个页面,其中的
    total_pages就是具体的页面数,接下来就是按照页码请求每一个页面。
  • parse_xiaoqu
    上面返回了每一个页面的信息,这个时候我们就把当前页面的小区列表拿到,而后,在针对小区列表,每一个小区进行一次请求。
  • parse_chengjiao
    解析小区的页面数,上面说到了,我们请求了每一个小区数据,这个小区肯定不止包含一页的数据,那么我们这个方法就是将这个小区包含的页面数抽取出来,而后针对每一个页面进行请求
  • parse_content
    这个方法就是解析具体的页面了,可以看到,这个方法里面包含了非常多的条件判断,这是因为,我们之前定义的item字段里面的信息,并不是每一个小区都有的,就是说,我们要的信息他不是一个规规矩矩的信息,很多的房源没有提供相关的信息,比如地铁,周边学校等等的信息,我们这里就是如果有这个信息,我们就把它提取出来,如果没有的话,我们就给他自定义一个内容
    。最后将item提交给item pipeline进行后续的处理。

由于这一节的信息比较多,我们就把它分为两个小节,在下一节中,我们对拿到的数据进行后续的处理。

Scrapy实战篇(一)之爬取链家网成交房源数据(上)的更多相关文章

  1. Scrapy实战篇(二)之爬取链家网成交房源数据(下)

    在上一小节中,我们已经提取到了房源的具体信息,这一节中,我们主要是对提取到的数据进行后续的处理,以及进行相关的设置. 数据处理 我们这里以把数据存储到mongo数据库为例.编写pipelines.py ...

  2. Scrapy实战篇(九)之爬取链家网天津租房数据

    以后有可能会在天津租房子,所以想将链家网上面天津的租房数据抓下来,以供分析使用. 思路: 1.以初始链接https://tj.lianjia.com/zufang/rt200600000001/?sh ...

  3. Python——Scrapy爬取链家网站所有房源信息

    用scrapy爬取链家全国以上房源分类的信息: 路径: items.py # -*- coding: utf-8 -*- # Define here the models for your scrap ...

  4. Python的scrapy之爬取链家网房价信息并保存到本地

    因为有在北京租房的打算,于是上网浏览了一下链家网站的房价,想将他们爬取下来,并保存到本地. 先看链家网的源码..房价信息 都保存在 ul 下的li 里面 ​ 爬虫结构: ​ 其中封装了一个数据库处理模 ...

  5. 适合初学者的Python爬取链家网教程

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: TinaLY PS:如有需要Python学习资料的小伙伴可以加点击下 ...

  6. 爬取链家网租房图 使用ImagesPipeline保存图片

    # 爬虫文件 # -*- coding: utf-8 -*- import scrapy import os from urllib import request from lianjia.items ...

  7. python - 爬虫入门练习 爬取链家网二手房信息

    import requests from bs4 import BeautifulSoup import sqlite3 conn = sqlite3.connect("test.db&qu ...

  8. Python爬虫项目--爬取链家热门城市新房

    本次实战是利用爬虫爬取链家的新房(声明: 内容仅用于学习交流, 请勿用作商业用途) 环境 win8, python 3.7, pycharm 正文 1. 目标网站分析 通过分析, 找出相关url, 确 ...

  9. Python爬取链家二手房源信息

    爬取链家网站二手房房源信息,第一次做,仅供参考,要用scrapy.   import scrapy,pypinyin,requests import bs4 from ..items import L ...

随机推荐

  1. mysql和mariadb支持insert delayed的问题

    分析一个开源项目,往数据库里添加日志,为了避免写入日志信息影响正常业务,日志的插入方式采用了insert delayed的方式. 打印其数据库语句,复制到mysql执行报如下错误: ERROR 161 ...

  2. scrapy python2升级python3遇到的坑

    换成Python3首先pycharm先执行: 然后看代码自己所需要的第三方库都要重新装 然后执行代码: 遇到这样的错如下: SyntaxError: invalid syntax 先检查print 所 ...

  3. makefile中的wildcard 、patsubst、

    在Makefile规则中,通配符会被自动展开.但在变量的定义和函数引用时,通配符将失效. 这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTE ...

  4. 使用VBA,优化处理Excel表格

    前言 上周末,XX给我抱怨:因为计算绩效奖金,把2个人的工资发错了,还被扣了500元.问的缘由得知,她每个月要处理十来个excel表格,每次都要手动修改里面的值,如果修改了一处,其他地方也要修改,然后 ...

  5. 移动应用调试之Inspect远程调试

    移动应用调试之Inspect远程调试 一.准备工作 chrome浏览器,建议最新版本 如果你点击inspect打开的DevTools窗口一片空白,且刷新无效时,那极有可能是由于被墙的缘故. 二.Ins ...

  6. Java生成带logo二维码

    目前生成二维码的方式有很多种,本例采用谷歌的zxing,去白边,添加logo等处理均在代码中有注释 demo连接 https://github.com/littlechaser/qrcode.git

  7. 编译QFileSystemModel

    QT在windows系统下可以直接安装,但有些时候,可以只编译一个类,这里需要有一些需要注意的.下面是github路径:https://github.com/1171597779/compile_of ...

  8. dos脚本

    关于dos命令行脚本编写   dos常用命令另查 开始之前先简单说明下cmd文件和bat文件的区别:在本质上两者没有区别,都是简单的文本编码方式,都可以用记事本创建.编辑和查看.两者所用的命令行代码也 ...

  9. pandas 将excel一列拆分成多列重新保存

    利用pd.read_excel   做到将第二列“EVT-LBL”按“-”分割后重新加三列在df后面 1 读取表格df 2. 分割第二列短横连接的数字,保存到df2---- 参考:str.spilt( ...

  10. erlang-gb_tree,gb_set

    gb_tree, gb_set, 均为一个二叉树.具体怎么实现,这边不在累赘,官方有手册, how to use ? 才是我们的重点 1. 初始化 1> gb_trees:empty().{0, ...