python链家网二手房数据爬取

python链家网二手房数据爬取

由于想练习一下Python的数据清洗,并将之前学习的机器学习内容付诸以实践,发现二手房市场的数据分析报告的内容十分匮乏。故此,通过Python爬取“链家网”杭州市二手房房源信息,辅助以Mongodb、PowerBI、Spss、Highchart实现数据的获取、数据的存储与查询、数据的初步统计描述、数据的可视化、数据的建模分析、数据的报表呈现。通过机器学习的随机森林算法,通过二手房源的自身特征来预测房源的关注度与累计看房数。

二手房数据的获取

主要使用到的第三方库有:
1.requests
2.Beautifulsoup
3.pymongo
4.multiprocess

    在前几次尝试的过程中发现,“链家网”会在IP频繁访问时,禁止我的IP的访问请求,造成数据爬取失败。沿着IP单一这个问题,尝试过使用代理IP,将免费代理IP网站上的IP地址以及端口号爬取下来,写入csv文件中,由于免费的代理质量不佳,需要自己写代码去验证IP的有效性,通过requests.get()中的timeout设置,当规定时间内没有出现响应的IP剔除,由此构建一个IP代理池。但在实践中发现,之前验证可以的代理,在短时间内很容易再次失效。
    之后查找资料后看到有前人通过服务器动态切换IP地址的方法避免爬虫被封,使用Tornado+Redis维护ADSL拨号服务器代理池,需要Linux的相关知识,下次补习Linux后再研究该怎么操作。后来寻思是不是可以从网站的M端进行数据爬取,有可能M端的反爬没有那么严,果然通过M端的爬取既没有限制IP连对访问的时间频率也没有做出限制。
    代码的思路是:

python链家网二手房数据爬取_第1张图片
尝试后发现M端的网站房源信息总共100页,也是通过异步加载的方式,通过检查network的XHR可以发现访问的链接只是在后面的pg参数加上页码。通过循环将3000套房源的链接爬取下来后并实现拼接。然后通过请求这些房源的链接来抓取具体数据。实现中发现可以先将房源链接写入txt文本,然后通过multiprocess的pool函数实现多进程处理,爬取速度显著提升。

from bs4 import BeautifulSoup
import requests
import pymongo
import time

client = pymongo.MongoClient('localhost',27017)
lianjia = client['lianjia']
house_info = lianjia['house_info']

headers = {'User-Agent':'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1'}
cookies = {'cookie':'lianjia_uuid=b02acfb6-322d-4b75-9e53-64867c6235fd; UM_distinctid=15dbaed3a951-05898fe8aa76ac-333f5902-100200-15dbaed3a966b0; _jzqckmp=1; select_city=330100; _jzqx=1.1502085288.1502440371.4.jzqsr=hz%2Elianjia%2Ecom|jzqct=/ershoufang/pg100/.jzqsr=hz%2Elianjia%2Ecom|jzqct=/ershoufang/rs/; _jzqy=1.1502079697.1502448823.5.jzqsr=baidu|jzqct=%E9%93%BE%E5%AE%B6.jzqsr=baidu; _smt_uid=5987eacf.1bc25f0c; _jzqa=1.99522161797814850.1502079697.1502440371.1502448823.13; _jzqc=1; _jzqb=1.2.10.1502448823.1; select_nation=1; lj-ss=1e5c8b6bb356c2aabadd162c97341948; _ga=GA1.2.1986363616.1502079701; _gid=GA1.2.133462306.1502371968; _gat=1; _gat_past=1; _gat_new=1; _gat_global=1; _gat_new_global=1; CNZZDATA1254525948=1219604799-1502445430-%7C1502445430; CNZZDATA1253491255=116476887-1502444529-%7C1502444529; Hm_lvt_9152f8221cb6243a53c83b956842be8a=1502408906,1502409437,1502432281,1502448821; Hm_lpvt_9152f8221cb6243a53c83b956842be8a=1502449140; lianjia_ssid=a1c3e71d-51bb-42ff-9d21-2aa15b143692'}
host = 'https://m.lianjia.com'

def get_house_href(page):
    url_list = ['https://m.lianjia.com/hz/ershoufang/pg{}/'.format(str(page)) for page in range(1,page+1)]
    for url in url_list:
        web_data = requests.get(url,headers=headers,cookies=cookies)
        web_data.encoding = 'utf8'
        # time.sleep(5)
        soup = BeautifulSoup(web_data.text,'lxml')
        href_list = soup.select('.pictext a')
        with open('href.txt', 'a+') as f:
            for href in href_list:
                full_href = host + href.get('href')
                f.write(full_href+'\n')



def get_detail(url):
    detail_data = requests.get(url,headers=headers,cookies=cookies)
    detail_data.encoding = 'utf8'
    detail_soup = BeautifulSoup(detail_data.text,'lxml')
    try:
        data = {
            'total_price':detail_soup.select('.red span')[0].text ,
            'house_struct':detail_soup.select('p.red')[1].text,
            'house_area':detail_soup.select('p.red')[2].text,
            'average_price':detail_soup.select('li.short')[0].text,
            'post_time': detail_soup.select('li.short')[1].text,
            'house_toward': detail_soup.select('li.short')[2].text,
            'num_floor': detail_soup.select('li.short')[3].text,
            'type_house': detail_soup.select('li.short')[4].text,
            'house_elevator': detail_soup.select('li.short')[5].text,
            'house_decorate': detail_soup.select('li.short')[6].text,
            'house_age': detail_soup.select('li.short')[7].text,
            'usage_house': detail_soup.select('li.short')[8].text,
            'right_belong': detail_soup.select('li.short')[9].text,
            'house_name':detail_soup.select('li.long a.post_ulog')[0].text,
            'house_location':detail_soup.select('p.marker_title')[0].text if len(detail_soup.select('p.marker_title'))==1 else None,
            'see_in_week':detail_soup.select('strong')[0].text,
            'accumulate_see':detail_soup.select('strong')[1].text,
            'fav_num':detail_soup.select('strong')[2].text,
            'suggest_price':detail_soup.select('.house_model_tit span.red')[0].text,

        }
        house_info.insert_one(data)
        print(data)
    except IndexError:
        pass


from anjuke import get_detail
from multiprocessing import Pool

if __name__== '__main__':
    list = []
    f = open('href.txt','r',encoding='gb2312')
    for i in f.readlines():
        list.append(i.strip())
    f.close()
    pool = Pool()
    pool.map(get_detail,list)
    pool.close()
    pool.join()

你可能感兴趣的:(python爬虫)