Scrapy实战篇(一)之爬取链家网成交房源数据(上)
今天,我们就以链家网南京地区为例,来学习爬取链家网的成交房源数据。
这里推荐使用火狐浏览器,并且安装firebug和firepath两款插件,你会发现,这两款插件会给我们后续的数据提取带来很大的方便。
首先创建一个名称为lianjia的项目。
需求分析
爬取数据的第一步当然是确定我们的需求,大方向就是我们想拿到南京地区的房源成交信息,但是具体的细节信息,我们需要从网页来看,,我们直接在浏览器中输入以下的网址https://nj.lianjia.com/chengjiao/,会显示南京地区的成交的房源信息,包括名称,房屋简介,地理位置,成交日期,成交价格,成交单价等详细信息,这样我们就确定了我们想要的信息,我们在items.py文件中定义如下的一些字段。
#items.py
from scrapy import Item,Field
class LianjiaItem(Item):
region = Field() #行政区域
href = Field() #房源链接
name = Field() #房源名称
style = Field() #房源结构
area = Field() #小区
orientation = Field() #朝向
decoration = Field() #装修
elevator = Field() #电梯
floor = Field() #楼层高度
build_year = Field() #建造时间
sign_time = Field() #签约时间
unit_price = Field() #每平米单价
total_price = Field() #总价
fangchan_class = Field() #房产类型
school = Field() #周边学校
subway = Field() #周边地铁
请注意,以上的信息,并不是每一套房源都有的,比如下面的地铁,学校,很多房源都是没有的。
问题
你会发现一个问题,每一个页面会呈现30条的房源信息,最下面一共可以显示100页,总计最多也就是3000条信息,南京地区的成交房源信息肯定不止这区区的3000条,那么如果直接从这个页面通过翻页来获取数据,最多只能获取到3000条信息,所以我们这里需要转思路。
还是这个页面,可以看到页面上部列出了南京地区的行政区,我们随意选择一个,会发现,新的页面依然是每一页30条,共计100页,但是我们有11个行政区,那么其数量也是翻了好几倍了。
这个时候,你可能还是不满足,我们想办法看一下是不是还可以进一步向下划分,没错那就是小区,我们把房源从11个行政区划分到小区上,以小区为单位,每一个小区上面还有房源数据,这样的话,我们的信息可以说比较全面了,当然了,我们需要做的工作也是要翻倍的。
总结
这里我们通过分析,总结出了如下的思路:
- 以行政区为单位,先获取南京地区所有的小区信息
- 以小区为单位,获取每一个小区里面的房源数据
- 最后就是获取具体的每一个房源的信息。
具体实施
现在明确了我们的思路,下面就开始具体的实施。
编写spider.py文件
from scrapy import Spider,Request
import re
from lxml import etree
import json
from urllib.parse import quote
from lianjia.items import LianjiaItem
class Lianjia_spider(Spider):
name = 'lianjia'
allowed_domains = ['nj.lianjia.com']
regions = {'gulou':'鼓楼',
'jianye':'建邺',
'qinhuai':'秦淮',
'xuanwu':'玄武',
'yuhuatai':'雨花台',
'qixia':'栖霞',
'jiangning':'江宁',
'liuhe':'六合',
'pukou':'浦口',
'lishui':'涟水',
'gaochun':'高淳'
}
def start_requests(self):
for region in list(self.regions.keys()):
url = "https://nj.lianjia.com/xiaoqu/" + region + "/"
yield Request(url=url, callback=self.parse, meta={'region':region}) #用来获取页码
def parse(self, response):
region = response.meta['region']
selector = etree.HTML(response.text)
sel = selector.xpath("//div[@class='page-box house-lst-page-box']/@page-data")[0] # 返回的是字符串字典
sel = json.loads(sel) # 转化为字典
total_pages = sel.get("totalPage")
for i in range(int(total_pages)):
url_page = "https://nj.lianjia.com/xiaoqu/{}/pg{}/".format(region, str(i + 1))
yield Request(url=url_page, callback=self.parse_xiaoqu, meta={'region':region})
def parse_xiaoqu(self,response):
selector = etree.HTML(response.text)
xiaoqu_list = selector.xpath('//ul[@class="listContent"]//li//div[@class="title"]/a/text()')
for xq_name in xiaoqu_list:
url = "https://nj.lianjia.com/chengjiao/rs" + quote(xq_name) + "/"
yield Request(url=url, callback=self.parse_chengjiao, meta={'xq_name':xq_name,
'region':response.meta['region']})
def parse_chengjiao(self,response):
xq_name = response.meta['xq_name']
selector = etree.HTML(response.text)
content = selector.xpath("//div[@class='page-box house-lst-page-box']") #有可能为空
total_pages = 0
if len(content):
page_data = json.loads(content[0].xpath('./@page-data')[0])
total_pages = page_data.get("totalPage") # 获取总的页面数量
for i in range(int(total_pages)):
url_page = "https://nj.lianjia.com/chengjiao/pg{}rs{}/".format(str(i+1), quote(xq_name))
yield Request(url=url_page, callback=self.parse_content, meta={'region': response.meta['region']})
def parse_content(self,response):
selector = etree.HTML(response.text)
cj_list = selector.xpath("//ul[@class='listContent']/li")
for cj in cj_list:
item = LianjiaItem()
item['region'] = self.regions.get(response.meta['region'])
href = cj.xpath('./a/@href')
if not len(href):
continue
item['href'] = href[0]
content = cj.xpath('.//div[@class="title"]/a/text()')
if len(content):
content = content[0].split() # 按照空格分割成一个列表
item['name'] = content[0]
item['style'] = content[1]
item['area'] = content[2]
content = cj.xpath('.//div[@class="houseInfo"]/text()')
if len(content):
content = content[0].split('|')
item['orientation'] = content[0]
item['decoration'] = content[1]
if len(content) == 3:
item['elevator'] = content[2]
else:
item['elevator'] = '无'
content = cj.xpath('.//div[@class="positionInfo"]/text()')
if len(content):
content = content[0].split()
item['floor'] = content[0]
if len(content) == 2:
item['build_year'] = content[1]
else:
item['build_year'] = '无'
content = cj.xpath('.//div[@class="dealDate"]/text()')
if len(content):
item['sign_time'] = content[0]
content = cj.xpath('.//div[@class="totalPrice"]/span/text()')
if len(content):
item['total_price'] = content[0]
content = cj.xpath('.//div[@class="unitPrice"]/span/text()')
if len(content):
item['unit_price'] = content[0]
content = cj.xpath('.//span[@class="dealHouseTxt"]/span/text()')
if len(content):
for i in content:
if i.find("房屋满") != -1: # 找到了返回的是非-1得数,找不到的返回的是-1
item['fangchan_class'] = i
elif i.find("号线") != -1:
item['subway'] = i
elif i.find("学") != -1:
item['school'] = i
yield item
我们对上面关键的地方进行解释:
- start_requests
这个就是我们以行政区为单位,目的是爬取每一个行政区的小区列表。 - parse
对行政区返回的response进行解析,我们目的是拿到这个大的行政区,包含多少个页面,其中的total_pages就是具体的页面数,接下来就是按照页码请求每一个页面。 - parse_xiaoqu
上面返回了每一个页面的信息,这个时候我们就把当前页面的小区列表拿到,而后,在针对小区列表,每一个小区进行一次请求。 - parse_chengjiao
解析小区的页面数,上面说到了,我们请求了每一个小区数据,这个小区肯定不止包含一页的数据,那么我们这个方法就是将这个小区包含的页面数抽取出来,而后针对每一个页面进行请求 - parse_content
这个方法就是解析具体的页面了,可以看到,这个方法里面包含了非常多的条件判断,这是因为,我们之前定义的item字段里面的信息,并不是每一个小区都有的,就是说,我们要的信息他不是一个规规矩矩的信息,很多的房源没有提供相关的信息,比如地铁,周边学校等等的信息,我们这里就是如果有这个信息,我们就把它提取出来,如果没有的话,我们就给他自定义一个内容
。最后将item提交给item pipeline进行后续的处理。
由于这一节的信息比较多,我们就把它分为两个小节,在下一节中,我们对拿到的数据进行后续的处理。
Scrapy实战篇(一)之爬取链家网成交房源数据(上)的更多相关文章
- Scrapy实战篇(二)之爬取链家网成交房源数据(下)
在上一小节中,我们已经提取到了房源的具体信息,这一节中,我们主要是对提取到的数据进行后续的处理,以及进行相关的设置. 数据处理 我们这里以把数据存储到mongo数据库为例.编写pipelines.py ...
- Scrapy实战篇(九)之爬取链家网天津租房数据
以后有可能会在天津租房子,所以想将链家网上面天津的租房数据抓下来,以供分析使用. 思路: 1.以初始链接https://tj.lianjia.com/zufang/rt200600000001/?sh ...
- Python——Scrapy爬取链家网站所有房源信息
用scrapy爬取链家全国以上房源分类的信息: 路径: items.py # -*- coding: utf-8 -*- # Define here the models for your scrap ...
- Python的scrapy之爬取链家网房价信息并保存到本地
因为有在北京租房的打算,于是上网浏览了一下链家网站的房价,想将他们爬取下来,并保存到本地. 先看链家网的源码..房价信息 都保存在 ul 下的li 里面 爬虫结构: 其中封装了一个数据库处理模 ...
- 适合初学者的Python爬取链家网教程
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: TinaLY PS:如有需要Python学习资料的小伙伴可以加点击下 ...
- 爬取链家网租房图 使用ImagesPipeline保存图片
# 爬虫文件 # -*- coding: utf-8 -*- import scrapy import os from urllib import request from lianjia.items ...
- python - 爬虫入门练习 爬取链家网二手房信息
import requests from bs4 import BeautifulSoup import sqlite3 conn = sqlite3.connect("test.db&qu ...
- Python爬虫项目--爬取链家热门城市新房
本次实战是利用爬虫爬取链家的新房(声明: 内容仅用于学习交流, 请勿用作商业用途) 环境 win8, python 3.7, pycharm 正文 1. 目标网站分析 通过分析, 找出相关url, 确 ...
- Python爬取链家二手房源信息
爬取链家网站二手房房源信息,第一次做,仅供参考,要用scrapy. import scrapy,pypinyin,requests import bs4 from ..items import L ...
随机推荐
- Redis for linux安装配置之—-源码安装
一‘redis单实例安装配置1.下载redis源码压缩包,并将其上传至服务器/usr/local2.解压redis源码压缩包 # tar -xzvf redis-3.2.12.tar.gz3.进入r ...
- python3-连接MySQL(mysql.connector与MySQLdb区别)
import mysql.connector cnx = mysql.connector.connect(user='scott', password='tiger',host='127.0.0.1' ...
- CST时区,MYSQL与JAVA-WEB服务器时间相差13个小时的问题
最近倒腾了一台阿里云主机,打算在上面装点自己的应用.使用docker安装了安装mysql后,发现数据库的存储的时间与java-web应用的时间差8个小时,初步怀疑是docker容器时区的问题.经过一系 ...
- Fiddle 抓包工具
1.在AutoResponder中拖取所需修改文件,在最下方进行文件替换,然后刷新页面: 2.连接手机: 在tools—options—connections下勾选Allow remote compu ...
- Vue(六) 表单与 v-model
学习使用 v-model 指令完成表单数据双向绑定 基本用法 表单控件在实际业务较为常见,比如单选,多选.下拉选择.输入框等,用他们可以完成数据的录入.校验.提交等.Vue.js 提供了 v-mode ...
- Win10系列:C#应用控件基础10
PasswordBox控件 在应用程序的登录界面中,有时需要用户输入用户名和密码进行身份验证,应用程序中的密码框可以通过使用PasswordBox控件来实现.PasswordBox控件与TextBox ...
- 并发,同步锁,Runnable,Callable,Future
1.并发: 在我们的操作系统中,同一个时间点,有N个线程都想访问同一个程序!但是cpu只能运行一个! 这种情况就是! 多个线程在 同一个时间点 访问同一个资源,会引发线程不安全的问题! 怎么解决这种不 ...
- 调用 LoadLibraryEx 失败,在 ISAPI 筛选器 "C:\Program Files\php\php5isapi.dll"
把 ISAPI 筛选器这里的php配置删掉,php改用fastcgi配置
- Android开发 ---构建对话框Builder对象,消息提示框、列表对话框、单选提示框、多选提示框、日期/时间对话框、进度条对话框、自定义对话框、投影
效果图: 1.activity_main.xml 描述: a.定义了一个消息提示框按钮 点击按钮弹出消息 b.定义了一个选择城市的输入框 点击按钮选择城市 c.定义了一个单选提示框按钮 点击按钮选择某 ...
- elasticsearch 使用快照进行备份
Elasticsearch也提供了备份集群中索引数据的策略——snapshot API.它会备份整个集群的当前状态和数据,并保存到集群中各个节点共享的仓库中.这个备份的进程是增量备份的,在第一次备份的 ...