如何高效地爬取链家的房源信息(四)

Python实现的链家网站的爬虫第四部分,最后一部分。


本系列文将以链家南京站为例,使用Python实现链家二手房源信息的爬虫,将数据爬取,并存入数据库中,以便使用。


本系列第一部分为基础:

如何高效地爬取链家的房源信息(一)


本系列第二部分为爬取小区信息:

如何高效地爬取链家的房源信息(二)


本系列第三部分为爬取在售二手房信息:

如何高效地爬取链家的房源信息(三)


本文是第四部分,爬取历史成交二手房信息并存入数据库,部分代码依赖于第一部分,同时依赖于第二部分的结果。


在前文中已经获取了小区信息,并存在了数据库中,直接读库遍历小区进行爬取:

def do_xiaoqu_chengjiao_spider(db_xq,db_cj):

    """

    批量爬取小区成交记录

    """

    count=0

    xq_list=db_xq.fetchall()

    for xq in xq_list:

        xiaoqu_chengjiao_spider(db_cj,xq[0],xq[1])

        count+=1

        print ('have spidered %d xiaoqu %s' % (count,xq[0]))

    print( 'done')


对某一个小区内的所有成交房源进行爬取,需要分页:

def xiaoqu_chengjiao_spider(db_cj, xq_url=u"https://nj.lianjia.com/xiaoqu/1411000000391/", xq_name=u"default"):

    """

    爬取小区成交记录

    """

    url = xq_url.replace('xiaoqu/','chengjiao/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_chengjiao_spider', xq_url)

        return

    except Exception as e:

        print(e)

        exception_write('xiaoqu_chengjiao_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']


    print(u"xiaoqu %s chengjiao totalpage %d" % (xq_name,total_pages));

    threads = []

    for i in range(total_pages):

        tmp= u'chengjiao/pg%dc'% (i + 1)

        url_page = url.replace('chengjiao/c',tmp);

        t = threading.Thread(target=chengjiao_spider, args=(db_cj, url_page))

        threads.append(t)

    for t in threads:

        t.start()

    for t in threads:

        t.join()


爬取单个页面内的成交记录信息:

def chengjiao_spider(db_cj, url_page=u"https://nj.lianjia.com/chengjiao/pg4c1411000000142/"):

    """

    爬取页面链接中的成交记录

    """

    print(u"爬取页面%s成交记录" % url_page);

    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('chengjiao_spider', url_page)

        return

    except Exception as e:

        print(e)

        exception_write('chengjiao_spider', url_page)

        return


    recodenum = 0;

    cjs = soup.find('ul', {'class': 'listContent'});

    cj_list = cjs.findAll('li', {})

    for cj in cj_list:

        info_dict = {}

        title = cj.find('div', {'class': 'title'});

        houseInfo = cj.find('div', {'class': 'houseInfo'});

        dealDate = cj.find('div', {'class': 'dealDate'});

        totalPrice = cj.find('div', {'class': 'totalPrice'});

        positionInfo = cj.find('div', {'class': 'positionInfo'});

        source = cj.find('div', {'class': 'source'});

        unitPrice = cj.find('div', {'class': 'unitPrice'});

        dealHouseInfo = cj.find('div', {'class': 'dealHouseInfo'});

        dealCycleeInfo = cj.find('div', {'class': 'dealCycleeInfo'});


        href = title.find('a')

        if not href:

            continue

        info_dict.update({u'链接': href.attrs['href']})

        content = title.text.split()

        if content:

            info_dict.update({u'小区名称': content[0]})

            info_dict.update({u'户型': content[1]})

            info_dict.update({u'面积': content[2]})


        content = houseInfo.text.split('|') #unicode(cj.find('div', {'class': 'con'}).renderContents().strip())

        if content:

            info_dict.update({u'朝向': content[0].strip()})

            if len(content) >= 2:

                info_dict.update({u'装修': content[1].strip()})

            if len(content) >= 3:

                info_dict.update({u'电梯': content[2].strip()})


        info_dict.update({u'签约时间': dealDate.text})

        info_dict.update({u'签约总价': totalPrice.text}) #注意值

        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()})  


        info_dict.update({u'来源': source.text})

        info_dict.update({u'签约单价': unitPrice.text}) #可能为*

        #content = dealHouseInfo.text.split()

        if dealHouseInfo != None:

            for span in dealHouseInfo.find('span', {'class': 'dealHouseTxt'}).findAll('span'):

                if span.text.find(u'房屋') != -1:

                    info_dict.update({u'税费': span.text})  # 满几年

                elif span.text.find(u'距') != -1:

                    info_dict.update({u'地铁': span.text})


        #content = dealCycleeInfo.text.split()

        if dealCycleeInfo != None:

            for span in dealCycleeInfo.find('span',{'class': 'dealCycleTxt'}).findAll('span'):

                if span.text.find(u'挂牌') != -1:

                    info_dict.update({u'挂牌价': span.text})

                elif span.text.find(u'成交周期') != -1:

                    info_dict.update({u'成交周期': span.text})


        command = gen_chengjiao_insert_command(info_dict)


        db_cj.execute(command, 1)

        recodenum += 1;

    print(u"爬取页面%s成交记录%d条" % (url_page,recodenum));



爬取的成交记录信息将被存储到数据库表中。




整个爬取过程还是很快的,在爬取完小区、在售、成交三类信息之后,就可以拿这些数据去进行想要做的分析了。


640?wx_fmt=jpeg

长按进行关注。


原文地址:https://www.cnblogs.com/protosec/p/11673335.html