如何高效地爬取链家的房源信息(三)
“Python实现的链家网站的爬虫第三部分。”
本系列文将以链家南京站为例,使用Python实现链家二手房源信息的爬虫,将数据爬取,并存入数据库中,以便使用。
本系列第一部分为基础:
本系列第二部分为爬取小区信息:
本文是第三部分,爬取在售二手房信息并存入数据库,部分代码依赖于第一部分,同时依赖于第二部分的结果。
在前文中已经获取了小区信息,并存在了数据库中,直接读库遍历小区进行爬取:
def do_xiaoqu_zaishou_spider(db_xq,db_zs):
"""
批量爬取小区在售
"""
count=0
xq_list=db_xq.fetchall()
for xq in xq_list:
xiaoqu_zaishou_spider(db_cj,xq[0])
count+=1
print ('have spidered zaishou %d xiaoqu %s' % (count,xq[0]))
print( 'done')
对某一个小区内的所有在售房源进行爬取,需要分页:
def xiaoqu_zaishou_spider(db_cj, xq_url=u"https://nj.lianjia.com/xiaoqu/1411000000391/"):
"""
爬取小区在售
"""
url = xq_url.replace('xiaoqu/','ershoufang/c');
try:
req = urllib.request.Request(url, headers=hds[random.randint(0, len(hds) - 1)])
source_code = urllib.request.urlopen(req, timeout=10).read()
plain_text = source_code.decode('utf-8')
soup = BeautifulSoup(plain_text,"html.parser")
except (urllib.request.HTTPError, urllib.request.URLError) as e:
print(e)
exception_write('xiaoqu_zaishou_spider', xq_url)
return
except Exception as e:
print(e)
exception_write('xiaoqu_zaishou_spider', xq_url)
return
content = soup.find('div', {'class': 'page-box house-lst-page-box'})
total_pages = 0
if content:
d = "d=" + content.get('page-data')
loc = {}
glb = {}
exec(d, glb, loc);
total_pages = loc['d']['totalPage']
threads = []
for i in range(total_pages):
tmp= u'ershoufang/pg%dc'% (i + 1)
url_page = url.replace('ershoufang/c',tmp);
t = threading.Thread(target=zaishou_spider, args=(db_cj, url_page))
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()
爬取单个页面内的在售信息:
def zaishou_spider(db_cj, url_page=u"https://nj.lianjia.com/chengjiao/pg4c1411000000142/"):
"""
爬取页面链接中的在售
"""
try:
req = urllib.request.Request(url_page, headers=hds[random.randint(0, len(hds) - 1)])
source_code = urllib.request.urlopen(req, timeout=10).read()
plain_text = source_code.decode('utf-8');
soup = BeautifulSoup(plain_text,"html.parser")
except (urllib.request.HTTPError, urllib.request.URLError) as e:
print(e)
exception_write('zaishou_spider', url_page)
return
except Exception as e:
print(e)
exception_write('zaishou_spider', url_page)
return
cjs = soup.find('ul', {'class': 'sellListContent'});
cj_list = cjs.findAll('li', {})
for cj in cj_list:
info_dict = {}
title = cj.find('div', {'class': 'title'});
houseInfo = cj.find('div', {'class': 'houseInfo'});
positionInfo = cj.find('div', {'class': 'positionInfo'});
followInfo = cj.find('div', {'class': 'followInfo'});
tag = cj.find('div', {'class': 'tag'});
totalPrice = cj.find('div', {'class': 'totalPrice'});
unitPrice = cj.find('div', {'class': 'unitPrice'});
href = title.find('a')
if not href:
continue
info_dict.update({u'链接': href.attrs['href']})
content = title.text
info_dict.update({u'房子描述': content})
content = houseInfo.text.split('|')
#有可能有别墅项,有可能无部分项
if content:
info_dict.update({u'小区名称': content[0].strip()})
if content[1].find(u'墅') != -1:
i=1;
else:
i=0;
if len(content) >= 2+i:
info_dict.update({u'户型': content[1+i].strip()})
if len(content) >= 3+i:
info_dict.update({u'面积': content[2+i].strip()})
if len(content) >= 4+i:
info_dict.update({u'朝向': content[3+i].strip()})
if len(content) >= 5+i:
info_dict.update({u'装修': content[4+i].strip()})
if len(content) >= 6+i:
info_dict.update({u'电梯': content[5+i].strip()})
content = positionInfo.text.split('-')
if len(content) >= 2:
info_dict.update({u'楼层年代楼型': content[0].strip()})
info_dict.update({u'区域': content[1].strip()})
else:
info_dict.update({u'区域': content[0].strip()})
content = followInfo.text.split('/')
for cont in content:
if cont.find(u'关注') != -1:
info_dict.update({u'关注': cont.strip()})
elif cont.find(u'带看') != -1:
info_dict.update({u'带看': cont.strip()})
elif cont.find(u'发布') != -1:
info_dict.update({u'发布时间': cont.strip()})
if tag != None:
tagall=tag.findAll('span')
for span in tagall:
if span.attrs['class'][0] ==u'taxfree':
info_dict.update({u'税费': span.text}) # 满几年
elif span.attrs['class'][0] ==u'subway':
info_dict.update({u'地铁': span.text})
elif span.attrs['class'][0] ==u'haskey':
info_dict.update({u'限制': span.text})
info_dict.update({u'挂牌价': totalPrice.text})
info_dict.update({u'挂牌单价': unitPrice.text})
command = gen_zaishou_insert_command(info_dict)
db_zs.execute(command, 1)
爬取的在售房源信息将被存储到数据库表中。
在接下来将说明如何爬取历史成交二手房信息,敬请期待。
长按进行关注。