在外工作,难免需要租房子,而链家是现在比较火的一个租房网站,本文主要是爬取链家在广州的租房信息,并且进行简单的数据分析:
1数据采集
这是通过网页查看到的HTML源码:
我们通过爬虫爬取HTML标签中的租房信息,然后存储到mysql数据库中:
(注:一般网站框架结构在某段时间过后会发生改变,到时代码可能需要重新修改!!)
编辑和调试脚本环境的IDE为Pycharm:
# -*- coding:utf-8 -*-
import requests
from bs4 import BeautifulSoup
import pandas as pd
from sqlalchemy import create_engine
import re
import bs4
import time
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive'
}
xingzhengqu = ['tianhe', 'yuexiu', 'liwan', 'haizhu', 'panyu', 'baiyun', 'huangpugz', 'zengcheng', 'huadou', 'nansha']
xingzhengqu_cn = ['天河', '越秀', '荔湾', '海珠', '番禺', '白云', '黄埔', '增城', '花都', '南沙']
# url为区域名,page为页码
def get_url(url, page):
# 获取网站所有源码
html = requests.get(url + '/pg%s' % str(page), headers=headers).text
# requests.get(url, headers={'Connection': 'close'});
# 获取每一条租房信息
table = BeautifulSoup(html, 'lxml').find_all('div', {'class': 'content__list--item'})
# 再定义一个变量,用以查找每个行政区最大的页码数
table_2 = BeautifulSoup(html, 'lxml')
# 使用正则找到最大页码数
pattern = re.compile('totalpage="(\\d+)"\\s')
last_page = re.findall(pattern, str(table_2))
# 租房面积正则表达式
pattern_1 = '</i>.*?(\\d+)㎡.*?<i>'
# 下面三个信息直接用bs4不方便,故使用正则来查找
# string = BeautifulSoup(html, 'lxml').find_all(attrs={'class': 'content__list--item--des'})
# string_1 = BeautifulSoup(html, 'lxml').find_all(attrs={'class': 'content__list--item--time oneline'})
# 租房面积
# pattern_mianji = re.findall(pattern_1, str(string), re.S)
# 租房发布时间点
pattern_2 = '<p.*?>.*?(.*?)</p>'
# pattern_updatetime = re.findall('<p.*?>.*?(.*?)</p>', str(string_1))
# 租房地区
pattern_quyu2 = re.compile('<a.*?>.*?</a>.*?>(.*?)</a>.*?title.*?</a>')
pattern_quyu3 = re.compile('<a.*?>.*?</a>.*?>.*?</a>.*?title.*?>(.*?)</a>')
pattern_fx = re.compile('\\s+(.*?)\\s+<span class="hide">')
pattern_lc = re.compile('.*?<span class="hide">\\n<i>/</i>\\n\\s+(.*?)\\n\\s+</span>')
pattern_cx = re.compile('\\s+<i>/</i>(.*?)\\s+<i>/</i>')
pattern_jg = re.compile('.*?<em>(.*?)</em>.*?')
result = []
for li in table:
try:
item = dict()
item[u'房屋描述'] = li.find('img').get('alt')
item[u'地区'] = re.findall(pattern_quyu2, str(li.find_all(attrs={'class': 'content__list--item--des'})))[0]
item[u'小区'] = re.findall(pattern_quyu3, str(li.find_all(attrs={'class': 'content__list--item--des'})))[0]
try:
item[u'近地铁否'] = li.find('i', {'class': 'content__item__tag--is_subway_house'}).get_text()
except AttributeError:
pass
item[u'房型'] = re.findall(pattern_fx, str(li.find_all(attrs={'class': 'content__list--item--des'})))[0]
item[u'面积'] = re.findall(pattern_1, str(li.find_all(attrs={'class': 'content__list--item--des'})), re.S)[0]
item[u'楼层'] = re.findall(pattern_lc, str(li.find_all(attrs={'class': 'content__list--item--des'})))[0]
item[u'朝向'] = re.findall(pattern_cx, str(li.find_all(attrs={'class': 'content__list--item--des'})))[0]
item[u'价格'] = re.findall(pattern_jg, str(li.find_all(attrs={'class': 'content__list--item-price'})))[0]
try:
item['押金'] = li.find('i', {'class': 'content__item__tag--deposit_1_pay_1'}).get_text()
item['公寓否'] = li.find('i', {'class': 'content__item__tag--authorization_apartment'}).get_text()
item['装修程度'] = li.find('i', {'class': 'content__item__tag--decoration'}).get_text()
item['看房时间'] = li.find('i', {'class': 'content__item__tag--is_key'}).get_text()
time.sleep(1)
except AttributeError:
pass
item[u'更新时间'] = re.findall(pattern_2, str(li.find_all(attrs={'class': 'content__list--item--time oneline'})))[0]
item[u'网站'] = li.find('a').get('href')
result.append(item)
except IndexError:
pass
return result, last_page
def get_quyu_data(area, x):
url = "https://gz.lianjia.com/zufang/%s" % area
page = 1
last_page = get_url(url, page)[1]
df = pd.DataFrame()
while True:
try:
result = get_url(url, page)[0]
except:
print("failed")
break
df = df.append(pd.DataFrame(result))
page += 1
if page > int(''.join(last_page)):
break
df['区域'] = '%s' % x
return df
def main():
column = ['房屋描述', '区域', '地区', '小区', '近地铁否', '房型', '面积', '楼层', '朝向', '价格', '押金', '公寓否', '装修程度', '看房时间', '更新时间', '网站']
engine = create_engine('mysql+mysqlconnector://root:123456@127.0.0.1/mysql?charset=utf8')
frame = pd.DataFrame()
for i in range(len(xingzhengqu)):
quyu = get_quyu_data(xingzhengqu[i], xingzhengqu_cn[i])
frame = frame.append(quyu)
frame = frame.reindex(columns=column)
frame.index = range(len(frame))
frame.to_sql('lianjia_zufang1', engine, if_exists='replace')
#设置延时,防止爬取过快被封IP和反爬
time.sleep(1)
if __name__ == '__main__':
main()
一共爬取到24334条租房数据:
一共搜集24334条记录,其中有些垃圾数据需要修正或者清除,可以通过数据库、或者pandas都可以清洗文本数据,接着进行数据分析
2、数据分析
2.1各区域租房量分布
柱形图可以看出房屋出租量排名前四分别为增城、天河、黄埔、越秀,都有超过2500套在出租。
2.2、各区域租房平均价格
从图可以看出租房价格前三依次是天河、越秀、海珠,最高为天河,每平方101.98元
2.3 房屋朝向对价格的影响
朝向为东南、西南、东的出租房价排名前三
2.4、楼层对出租房价的影响
从图中可以看出大多数情况下一般高楼层的房价还是较高,楼层超过30层基本租房单价达到71.27元/平方 平均水平,大多数房子分布在5-34楼
2.5、时间对租房价格的影响
从图中可以看到一般7月份房价开始上涨,8-9月份房价变化不大,10月份的涨幅最大,房价达119.99元/平方,进入11月份后房价开始下跌
2.6、房子面积对租房价格的影响
整体来看,面积越大,房价越高。
2.7、临近地铁对租房价格的影响
从图中可以看出租房临近地铁平均租房价格高出将近一倍
2.8 各区域下地区楼盘数分布
天河区的租房大都集中在棠下、东圃、天河公园
越秀区的租房大都集中在建设路、淘金、东山口、小北
番禺区的租房大都集中在市桥、桥南、大石、祈福新村
白云区租房大都集中在机场路、新市、嘉禾望岗、同德路、景泰、金沙洲
海珠区租房大都集中在滨江东、赤岗、工业大道中、金碧、万胜围、新港西
荔湾区租房大都集中在窖口、芳村、广钢新城、龙津
黄浦区租房主要集中在科学城、文冲、香雪、夏园
南沙区租房主要集中在金州、南沙区府、进港大道、南沙港
增城租房主要集中在凤凰城、朱村、新塘北、百江
3、词云
最后来个彩蛋,用房屋描述弄个词云