目标
通过Scrapy
爬取链家二手房数据,地址 https://bj.lianjia.com/ershoufang/ ,并对爬取到的数据进行处理,存储到csv文件中。
环境
博主是在Windows
平台使用PyCharm
基于Python 3.7
和Scrapy 2.0.1
编写爬虫,不赘述环境配置了。
建立项目
右键Scrapy
文件夹,选择在终端中打开
在终端中输入scrapy startproject lianjiaershou
,其中lianjiaershou
为项目名。
更改items.py
import scrapy
# 为增强可读性,直接以中文作为变量名
class MyItem(scrapy.Item):
标题 = scrapy.Field()
小区 = scrapy.Field()
区域 = scrapy.Field()
户型_室 = scrapy.Field()
户型_厅 = scrapy.Field()
面积 = scrapy.Field()
朝向 = scrapy.Field()
装修 = scrapy.Field()
楼层 = scrapy.Field()
建成年份 = scrapy.Field()
建筑结构 = scrapy.Field()
关注人数 = scrapy.Field()
已发布日 = scrapy.Field()
总价 = scrapy.Field()
单价 = scrapy.Field()
满二 = scrapy.Field()
满五 = scrapy.Field()
近地铁 = scrapy.Field()
分析网页
复制三个标题
的xpath,不难找到规律:
/html/body/div[4]/div[1]/ul/li[1]/div[1]/div[1]/a
/html/body/div[4]/div[1]/ul/li[2]/div[1]/div[1]/a
/html/body/div[4]/div[1]/ul/li[3]/div[1]/div[1]/a
只需迭代爬取每个li区块即可。
新建并更改spider.py
在spider
文件夹中新建spider.py
,并键入:
# 为了方便更改,设置全局变量
page = 100 # 爬取页数
area = "haidian" # 爬取城区
import scrapy
from lianjiaershou.items import MyItem
class mySpider(scrapy.spiders.Spider):
name = "lianjiaershou"
allowed_domains = ["bj.lianjia.com"]
start_urls = []
# 依次将第1页到第page页放入开始连接队列
for i in range(1 , page+1):
start_urls.append("https://bj.lianjia.com/ershoufang/{}/pg{}/".format(area, i))
# 如果你希望一次爬取多个城区,可以使用如下语句
'''
areas = ['dongcheng', 'xicheng', 'haidian', 'chaoyang']
for each in areas:
for i in range(1, page+1):
start_urls.append("https://bj.lianjia.com/ershoufang/{}/pg{}/".format(each, i))
'''
def parse(self, response):
item = MyItem ()
for each in response.xpath("/html/body/div[4]/div[1]/ul/*"):
# item['城区'] = response.url.split('/')[-3] # 如果你一次性爬取了多个城区,可以使用该语句
item['标题'] = each.xpath("div/div[1]/a/text()").extract()[0]
item['小区'] = each.xpath("div/div[2]/div/a[1]/text()").extract()[0]
item['区域'] = each.xpath("div/div[2]/div/a[2]/text()").extract()[0]
# 由于信息以字符串形式存在,并以' | '分隔,故创建临时变量,分割字符串,存为列表
temp = each.xpath("div/div[3]/div/text()").extract()[0].split(' | ')
# temp[0]的格式是n室m厅
item['户型_室'] = temp[0][0]
item['户型_厅'] = temp[0][-2]
item['面积'] = temp[1][:-2] # 去除汉字'平米'
item['朝向'] = temp[2]
item['装修'] = temp[3]
item['楼层'] = temp[4]
item['建成年份'] = temp[5][:-2] # 去除汉字'年建'
if len(temp) <= 6 or temp[6]=='暂无数据':
item['建筑结构'] = 'N/A'
else:
item['建筑结构'] = temp[6]
temp = each.xpath("div/div[4]/text()").extract()[0].split(' / ')
item['关注人数'] = temp[0][:-3]
# 日期格式可分为 n天以前前 n个月以前 一年前
if temp[1][1] == '天':
item['已发布日'] = int(temp[1][0])
elif temp[1][1] == '个':
item['已发布日'] = int(temp[1][0]) * 30
else:
item['已发布日'] = 360
if each.xpath("div/div[5]/span[@class='taxfree']/text()").extract():
item['满五'] = True
else:
item['满五'] = False
if each.xpath("div/div[5]/span[@class='five']/text()").extract():
item['满二'] = True
else:
item['满二'] = False
if each.xpath("div/div[5]/span[@class='subway']/text()").extract():
item['近地铁'] = True
else:
item['近地铁'] = False
item['总价'] = each.xpath("div/div[6]/div[1]/span/text()").extract()[0]
item['单价'] = each.xpath("div/div[6]/div[2]/span/text()").extract()[0][2:-4] # 去除汉字'单价*元/平米'
yield item
更改setting.py
BOT_NAME = 'lianjiaershou'
SPIDER_MODULES = ['lianjiaershou.spiders']
NEWSPIDER_MODULE = 'lianjiaershou.spiders'
# 不遵守机器人协议
ROBOTSTXT_OBEY = False
# 客户端伪装
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36'
# 防止ip被封,每页延迟1s爬取
DOWNLOAD_DELAY = 1
新建begin.py
在项目文件夹中新建begin.py
,内容为:
from scrapy import cmdline
from lianjiaershou.spiders import spider # 用于从linajiaershou/spiders/spider.py读取area变量
import os
if os.path.exists("data/data_{}.csv".format(spider.area)):
os.remove("data/data_{}.csv".format(spider.area)) # 为了防止文件已存在导致索引和数据重复,先删除将要生成的文件
cmdline.execute("scrapy crawl lianjiaershou -o data/data_{}.csv -t csv".format(spider.area).split())
# 如果你不想以spider.py中area命名文件,请参考以下
'''
if os.path.exists("data/data.csv"):
os.remove("data/data.csv") # 为了防止文件已存在导致索引和数据重复,先删除将要生成的文件
cmdline.execute("scrapy crawl lianjiaershou -o data/data.csv -t csv".split())
'''
其中lianjiaershou
为爬虫名(无须与项目名相同)。目的是为了方便运行爬虫。(忽略图中代码内容,只看项目结构就好,只是博主懒得再重新截图了)
这里直接使用scrapy命令保存到csv,pipelines.py
保持默认即可。
运行爬虫
运行begin.py
,成功爬取到数据。这里只列举部分。
关注人数,区域,单价,小区,已发布日,建成年份,建筑结构,总价,户型_厅,户型_室,朝向,标题,楼层,满二,满五,装修,近地铁,面积
119,四季青,106072,美丽园 ,360,2000,板楼,1160,1,2,南 北,美丽园小区一层带花园两居室,位置安静临水系,底层(共6层),False,True,简装,True,109.36
147,厂洼,99173,厂洼小区 ,360,1990,塔楼,719,1,3,西南,厂洼小区 西南向三居 带电梯 采光好,中楼层(共20层),True,False,简装,True,72.5
72,甘家口,93214,国兴家园 ,360,2000,塔楼,1390,1,3,东南,东南向三居室,户型方正,随时可看,低楼层(共24层),False,True,简装,True,149.12
149,玉泉路,61400,玉海园二里 ,360,1998,板塔结合,610,2,2,西北,海淀玉泉路 玉海园电梯两居室 满五年商品房 诚意出售,高楼层(共11层),False,True,简装,True,99.35
197,田村,78543,雅世合金公寓 ,360,2011,板塔结合,709,1,2,东 西,雅世合金 十大科技系统居住舒适度高 户型好,中楼层(共9层),False,True,精装,True,90.27
备注
由于通过scrapy命令行写csv是a
模式且无法更改,所以如果多次运行会导致索引和数据重复。该问题已解决,已经修改代码。
也可通过pipelines.py
实现,本文不再赘述。