鏈家APP上有很多在售房源信息以及成交房源信息,如果可以把這些信息爬下來累颂,可以得到很多有價值的信息侣集。因此本文將講一講如何爬取這些數(shù)據(jù)坛增,并保存下來供以后分析。
本文將介紹以下幾個方面:
程序介紹
- 該程序支持爬取鏈家在線二手房數(shù)據(jù)雕欺,歷史成交數(shù)據(jù)岛马,在線租房數(shù)據(jù)和指定城市所有小區(qū)數(shù)據(jù)。
- 數(shù)據(jù)存儲目前支持三種數(shù)據(jù)庫格式(mysql屠列,postgreSql, Sqlite3)啦逆。
- 由于鏈家網(wǎng)采取對IP限流設(shè)置,所以該程序沒有采取多線程爬取笛洛,并且限制了爬取速度來防止被封夏志。
- 提供mysql數(shù)據(jù)轉(zhuǎn)到ES的解決方案,方便進行數(shù)據(jù)可視化分析苛让。
使用教程
- 源碼地址 https://github.com/XuefengHuang/lianjia-scrawler 如果喜歡盲镶,請給個star支持一下,謝謝蝌诡!
- 下載源碼并安裝依賴包
1. git clone https://github.com/XuefengHuang/lianjia-scrawler.git
2. cd lianjia-scrawler
# If you'd like not to use [virtualenv](https://virtualenv.pypa.io/en/stable/), please skip step 3 and 4.
3. virtualenv lianjia
4. source lianjia/bin/activate
5. pip install -r requirements.txt
- 設(shè)置數(shù)據(jù)庫信息以及爬取城市行政區(qū)信息(支持三種數(shù)據(jù)庫格式)
DBENGINE = 'mysql' #ENGINE OPTIONS: mysql, sqlite3, postgresql
DBNAME = 'test'
DBUSER = 'root'
DBPASSWORD = ''
DBHOST = '127.0.0.1'
DBPORT = 3306
CITY = 'bj' # only one, shanghai=sh shenzhen=sh......
REGIONLIST = [u'chaoyang', u'xicheng'] # 只支持拼音
- 運行
python scrawl.py
! (請注釋14行如果已爬取完所想要的小區(qū)信息) - 可以修改
scrawl.py
來只爬取在售房源信息或者成交房源信息或者租售房源信息
實現(xiàn)思路
- 開始抓取前先觀察下目標頁面或網(wǎng)站的結(jié)構(gòu)溉贿,其中比較重要的是URL的結(jié)構(gòu)。鏈家網(wǎng)的二手房列表頁面共有100個浦旱,URL結(jié)構(gòu)為http://bj.lianjia.com/ershoufang/pg9/宇色,其中bj表示城市,/ershoufang/是頻道名稱颁湖,pg9是頁面碼宣蠕。我們要抓取的是北京的二手房頻道,所以前面的部分不會變甥捺,屬于固定部分抢蚀,后面的頁面碼需要在1-100間變化,屬于可變部分镰禾。將URL分為兩部分皿曲,前面的固定部分賦值給url,后面的可變部分使用for循環(huán)吴侦。我們以根據(jù)小區(qū)名字搜索二手房出售情況為例:
BASE_URL = u"http://bj.lianjia.com/"
url = BASE_URL + u"ershoufang/rs" + urllib2.quote(communityname.encode('utf8')) + "/"
total_pages = misc.get_total_pages(url) //獲取總頁數(shù)信息
for page in range(total_pages):
if page > 0:
url_page = BASE_URL + u"ershoufang/pg%drs%s/" % (page+1, urllib2.quote(communityname.encode('utf8')))
//獲取總頁數(shù)信息代碼
def get_total_pages(url):
source_code = get_source_code(url)
soup = BeautifulSoup(source_code, 'lxml')
total_pages = 0
try:
page_info = soup.find('div',{'class':'page-box house-lst-page-box'})
except AttributeError as e:
page_info = None
if page_info == None:
return None
page_info_str = page_info.get('page-data').split(',')[0] #'{"totalPage":5,"curPage":1}'
total_pages = int(page_info_str.split(':')[1])
return total_pages
- 頁面抓取完成后無法直接閱讀和進行數(shù)據(jù)提取屋休,還需要進行頁面解析。我們使用BeautifulSoup對頁面進行解析备韧。
soup = BeautifulSoup(source_code, 'lxml')
nameList = soup.findAll("li", {"class":"clear"})
- 完成頁面解析后就可以對頁面中的關(guān)鍵信息進行提取了劫樟。下面我們分別對房源各個信息進行提取。
for name in nameList: # per house loop
i = i + 1
info_dict = {}
try:
housetitle = name.find("div", {"class":"title"})
info_dict.update({u'title':housetitle.get_text().strip()})
info_dict.update({u'link':housetitle.a.get('href')})
houseaddr = name.find("div", {"class":"address"})
info = houseaddr.div.get_text().split('|')
info_dict.update({u'community':info[0].strip()})
info_dict.update({u'housetype':info[1].strip()})
info_dict.update({u'square':info[2].strip()})
info_dict.update({u'direction':info[3].strip()})
housefloor = name.find("div", {"class":"flood"})
floor_all = housefloor.div.get_text().split('-')[0].strip().split(' ')
info_dict.update({u'floor':floor_all[0].strip()})
info_dict.update({u'years':floor_all[-1].strip()})
followInfo = name.find("div", {"class":"followInfo"})
info_dict.update({u'followInfo':followInfo.get_text()})
tax = name.find("div", {"class":"tag"})
info_dict.update({u'taxtype':tax.get_text().strip()})
totalPrice = name.find("div", {"class":"totalPrice"})
info_dict.update({u'totalPrice':int(totalPrice.span.get_text())})
unitPrice = name.find("div", {"class":"unitPrice"})
info_dict.update({u'unitPrice':int(unitPrice.get('data-price'))})
info_dict.update({u'houseID':unitPrice.get('data-hid')})
except:
continue
- 提取完后,為了之后數(shù)據(jù)分析叠艳,要存進之前配置的數(shù)據(jù)庫中奶陈。
model.Houseinfo.insert(**info_dict).upsert().execute()
model.Hisprice.insert(houseID=info_dict['houseID'], totalPrice=info_dict['totalPrice']).upsert().execute()
數(shù)據(jù)存儲
- 可支持數(shù)據(jù)庫:mysql,postgreSql, Sqlite3
- 數(shù)據(jù)庫信息:
Community小區(qū)信息(id, title, link, district, bizcurcle, taglist)
Houseinfo在售房源信息(houseID, title, link, community, years, housetype, square, direction, floor, taxtype, totalPrice, unitPrice, followInfo, validdate)
Hisprice歷史成交信息(houseID附较,totalPrice尿瞭,date)
Sellinfo成交房源信息(houseID, title, link, community, years, housetype, square, direction, floor, status, source,, totalPrice, unitPrice, dealdate, updatedate)
Rentinfo租售房源信息 (houseID, title, link, region, zone, meters, other, subway, decoration, heating, price, pricepre, updatedate)
可視化分析
- 首先需要同步mysql數(shù)據(jù)到ES里,然后利用kibana進行數(shù)據(jù)分析翅睛。同步的部分可以利用該工具
-
截圖示例:
房源信息.png
房源信息json格式數(shù)據(jù).png
房源地區(qū)分布圖.png