爬取链家租房数据,数据处理,进行可视化分析

 lianjiaspider.py

import asyncio
import aiohttp
import pandas as pd
from lxml import etree


class LianjiaSpider(object):

    def __init__(self):
        self._headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36"}
        self._data = list()

    async def get(self, url):
        async with aiohttp.ClientSession() as session:
            try:
                async with session.get(url, headers=self._headers, timeout=3) as resp:
                    if resp.status == 200:
                        result = await resp.text()
                        return result
            except Exception as e:
                print(e.args)

    async def parse_html(self):
        for page in range(1, 77):
            url = "https://sjz.lianjia.com/zufang/pg{}/".format(page)
            print("正在爬取{}".format(url))
            html = await self.get(url)  # 获取网页内容
            html = etree.HTML(html)
            self.parse_page(html)
            print("正在存储数据....")
            data = pd.DataFrame(self._data)
            data.to_csv("lianjia.csv", encoding='utf_8_sig')  # 写入文件

    def parse_page(self, html):
        info_panel = html.xpath("//div[@class='info-panel']")
        for info in info_panel:
            region = info.xpath(".//span[@class='region']/text()")
            zone = info.xpath(".//span[@class='zone']/span/text()")
            meters = info.xpath(".//span[@class='meters']/text()")
            where = info.xpath(".//div[@class='where']/span[4]/text()")

            con = info.xpath(".//div[@class='con']/text()")
            floor = con[0]  # 楼层
            type = con[1]  # 样式

            agent = info.xpath(".//div[@class='con']/a/text()")[0]

            has = info.xpath(".//div[@class='left agency']//text()")

            price = info.xpath(".//div[@class='price']/span/text()")[0]
            price_pre = info.xpath(".//div[@class='price-pre']/text()")[0]
            look_num = info.xpath(".//div[@class='square']//span[@class='num']/text()")[0]

            one_data = {
                "region": region,
                "zone": zone,
                "meters": meters,
                "where": where,
                "louceng": floor,
                "type": type,
                "xiaoshou": agent,
                "has": has,
                "price": price,
                "price_pre": price_pre,
                "num": look_num
            }
            self._data.append(one_data)  # 添加数据

    def run(self):
        loop = asyncio.get_event_loop()
        tasks = [asyncio.ensure_future(self.parse_html())]
        loop.run_until_complete(asyncio.wait(tasks))


if __name__ == '__main__':
    Lian_jia = LianjiaSpider()
    Lian_jia.run()

lianjia.csv

  ,has,louceng,meters,num,price,price_pre,region,type,where,xiaoshou,zone
0,['集中供暖'],高楼层(共33层),['127.86平米\xa0\xa0'],0,2300,2018.11.08 更新,['凤凰城梧桐苑\xa0\xa0'],板楼,['南'],南焦租房,['3室2厅\xa0\xa0']
1,['集中供暖'],中楼层(共6层),['55平米\xa0\xa0'],0,1200,2018.11.04 更新,['华兴小区\xa0\xa0'],板楼,['南'],世纪公园租房,['1室1厅\xa0\xa0']
2,['集中供暖'],中楼层(共6层),['138平米\xa0\xa0'],0,2400,2018.11.04 更新,['河冶小区\xa0\xa0'],板楼,['南 北'],跃进租房,['3室2厅\xa0\xa0']
3,['集中供暖'],低楼层(共6层),['90平米\xa0\xa0'],1,1500,2018.11.06 更新,['瑞国花园\xa0\xa0'],板楼,['南'],跃进租房,['2室2厅\xa0\xa0']
4,['集中供暖'],低楼层(共14层),['180平米\xa0\xa0'],0,3500,2018.11.13 更新,['华脉新村\xa0\xa0'],板楼,['南 北'],四十中学租房,['4室2厅\xa0\xa0']
5,"['近地铁', '随时看房', '集中供暖']",中楼层(共40层),['57平米\xa0\xa0'],0,3000,2018.11.09 更新,['华润大厦\xa0\xa0'],塔楼,['西'],南长租房,['1室1厅\xa0\xa0']
6,"['近地铁', '随时看房', '集中供暖']",中楼层(共40层),['42.56平米\xa0\xa0'],0,2200,2018.11.09 更新,['华润大厦\xa0\xa0'],塔楼,['南'],南长租房,['1室1厅\xa0\xa0']
7,['集中供暖'],中楼层(共34层),['148平米\xa0\xa0'],0,2500,2018.11.08 更新,['北城国际B区\xa0\xa0'],板楼,['南 北'],沿东租房,['3室2厅\xa0\xa0']
8,"['近地铁', '随时看房', '集中供暖']",中楼层(共40层),['40.09平米\xa0\xa0'],0,2100,2018.11.09 更新,['华润大厦\xa0\xa0'],塔楼,['南'],南长租房,['1室1厅\xa0\xa0']
9,"['近地铁', '集中供暖']",低楼层(共33层),['185平米\xa0\xa0'],0,22000,2018.11.10 更新,['青鸟中山华府\xa0\xa0'],板楼,['北'],大经租房,['1室1厅\xa0\xa0']
10,"['近地铁', '集中供暖']",低楼层(共33层),['242平米\xa0\xa0'],0,29000,2018.11.05 更新,['青鸟中山华府\xa0\xa0'],板楼,['北'],大经租房,['1室1厅\xa0\xa0']

去除无用字符

import re

f = open("lian_jia.csv", 'w', encoding='utf-8')
filename = 'lianjia.csv'
with open(filename, 'r', encoding='utf-8')as file:
    frd = file.readlines()
    for i in frd:
        pattern = re.compile(r'xa0')
        out = re.sub(pattern, '', i)
        s = "".join("".join("".join(out.split("\\\\")).split("']")).split("['"))
        d = "".join(s.split("平米"))
        f.write(d)

lian_jia.csv

 ,has,louceng,meters,num,price,price_pre,region,type,where,xiaoshou,zone
0,集中供暖,高楼层(共33层),127.86,0,2300,2018.11.08 更新,凤凰城梧桐苑,板楼,南,南焦租房,3室2厅
1,集中供暖,中楼层(共6层),55,0,1200,2018.11.04 更新,华兴小区,板楼,南,世纪公园租房,1室1厅
2,集中供暖,中楼层(共6层),138,0,2400,2018.11.04 更新,河冶小区,板楼,南 北,跃进租房,3室2厅
3,集中供暖,低楼层(共6层),90,1,1500,2018.11.06 更新,瑞国花园,板楼,南,跃进租房,2室2厅
4,集中供暖,低楼层(共14层),180,0,3500,2018.11.13 更新,华脉新村,板楼,南 北,四十中学租房,4室2厅
5,"近地铁', '随时看房', '集中供暖",中楼层(共40层),57,0,3000,2018.11.09 更新,华润大厦,塔楼,西,南长租房,1室1厅
6,"近地铁', '随时看房', '集中供暖",中楼层(共40层),42.56,0,2200,2018.11.09 更新,华润大厦,塔楼,南,南长租房,1室1厅
7,集中供暖,中楼层(共34层),148,0,2500,2018.11.08 更新,北城国际B区,板楼,南 北,沿东租房,3室2厅
8,"近地铁', '随时看房', '集中供暖",中楼层(共40层),40.09,0,2100,2018.11.09 更新,华润大厦,塔楼,南,南长租房,1室1厅
9,"近地铁', '集中供暖",低楼层(共33层),185,0,22000,2018.11.10 更新,青鸟中山华府,板楼,北,大经租房,1室1厅
10,"近地铁', '集中供暖",低楼层(共33层),242,0,29000,2018.11.05 更新,青鸟中山华府,板楼,北,大经租房,1室1厅

可视化户型数量分布

import pandas as pd
import matplotlib.pyplot as plt

house = pd.read_csv('lian_jia.csv', names=['', 'has', 'louceng', 'meters', 'num', 'price', 'price_pre', 'region', 'type', 'where','xiaoshou', 'zone'])
zone = house['zone'].value_counts()
plt.rcParams['font.sans-serif'] = ['FangSong']  # 指定默认字体
asd, sdf = plt.subplots(1, 1, dpi=200)  # 设置画布
zone.head(10).plot(kind='bar', x='zone', y='size', title='户型数量分布', ax=sdf)  # 获取前10条数据
plt.legend(['数量'])
plt.show()

柱状图

 

  • 9
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
数据分析实战项⽬--链家租房数据可视化分析 导语:前⼏天舍友送了⼀本介绍的书籍,由此联想到,好久没有爬过⽹站了,但之前学的东西差不多全还给秦⽼板了(给我们上python的 ⽼师)。于是⽴马上⽹找了⼏篇博客,重温了⼀下⼏个包的知识点,动了⼀下⼩⼿,这不就有了等下要和你们讲的故事喽。 (⼀)项⽬介绍 (⼀)项⽬介绍 1. ⼯具 ⼯具 pycharm 2020.1.5 2. 内容 内容 本项⽬分为两部分: + 数据可视化分析 (1)爬⾍:⽤包爬取链家租房⽹页内容——BeautifulSoup解析——re正则表达式匹配我们需要的内容——sqlite3保存数据 (2)分析:pandas清洗分析数据——pyecharts进⾏可视化分析 (⼆)爬⾍部分 (⼆)爬⾍部分 ( (1)爬⾍第⼀步,了解我们将要爬取⽹页的信息 )爬⾍第⼀步,了解我们将要爬取⽹页的信息 如图所⽰:⼩框是链家⽹页租房的⽹址,⼤框是我们想要从⽹页中获取的内容。 由于链家的限制, 把页⾯往下拉到底部就可以看见,⼀次最多只能访问100页,⼀个页⾯有30套房,就是说,我们⼀次最多能看见 3000套房⼦的信息。但是实际上的租房房源远不3000。怎么办呢?我们可以通过增加限制条件来获取到尽量全的房源。 现在问题⼜来了,按区域爬⾍,区域我们是确定知道的,因为北京统共就那么⼏个区,但是⽹址中还需要知道各个区域的页数,各个 区域的页数⼜不相同,那么各个区域分别有多少页呢?这⾥我⽤了⼀个⽐较笨的⽅法,但⽅法虽笨,实现还是挺简单的,就是先爬取每个区 域的第⼀页,页⾯的最后有显⽰最⼤⽹页数,由此我们就可以得到最⼤⽹页数。现在先Fn+F12⼀下来看看⽹页的html⽂件吧~ 从上图,我们可以看出页数的信息在div class="content__pg"下⾯的内容,由此我们可以据其写出正则匹配表达式,并在div class="content__pg"下⾯的内容找到最⼤页数。 本次爬⾍⽤的是requests包,⾸先构造⼀个响应头部header,⽤于伪装,然后构造get请求并发起,将爬取下来的数据存于html中, 详见代码ask_url函数。 在get_page函数中调⽤ask_url函数,循环爬取每个区的第⼀页,⼀边爬⼀边⽤BeautifulSoup解析,并在解析过的数据中,⽤ re.findall()在div class="content__pg"下⾯的内容匹配找出最⼤页数。get_page函数中⽤了两个for循环,⼀个调⽤regions中的区,然 后爬⾍,⼀个⽤来查找爬取内容的最⼤页数。(本次爬⾍的限制条件,即区域,只有13个,其他4个较为边缘的区没有计⼊) ( (2)正式爬取⽹页信息并解析匹配 )正式爬取⽹页信息并解析匹配 从上⾯,我们得到了每个区的页数,并保存于pagelist⾥⾯,返回。接下来,就要正式爬取我们想要的内容了。⾸先,设置⼀个空列 表来存放我们解析匹配后得到的数据。两个for循环,调⽤ask_url函数,才能得到regions⾥⾯所有区各⾃的页数的全部内容。 爬取⼀页内容,解析⼀页。 再⼀次Fn+F12,可以看见,我们想要获取的内容,都在div class_="content__list--item",我们先print⼀个或者多个解析过后的 soup,观察其结构和内容,可根据其中内容⽤re.compile()构造出我们所需内容的正则表达式,在这⾥就不⼀⼀展开了,有兴趣的uu找找 相关正则表达式的博客。 之后就开始匹配我们需要的内容,⽤re包⾥⾯的findall⽅法找出和正则表达式匹配的内容,并先将内容暂时存在⼀个data列表⾥,等 到所有想要得到的内容都匹配完成之后,再加⼊datalist列表中。这⼀步,我们会得到所有想要的信息。 1 import requests 2 from bs4 import BeautifulSoup 3 import re 4 import sqlite3 5 import pandas as pd 6 7 def main(): 8 baseurl = 'https://bj.lianjia.com/zufang/' 9 pagelist = get_page(baseurl) #得到每个区的页数 10 datalist = get_data(baseurl, pagelist) #得到所有数据 11 dbpath = "zufang.db" 12 savedata_2_db(datalist, dbpath) #存⼊数据库 13 14 findpage = re.compile(r'data-totalpage="(\d*)" data-ur') #构建正则匹配,最⼤页数 15 16 17 def get_page(baseurl): #找出每个
以下是使用Python爬取链家租房数据的示例代码: ```python import requests from bs4 import BeautifulSoup # 设置请求头,模拟浏览器访问 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3' } # 设置要爬取的城市和页码范围 city = 'bj' # 北京 start_page = 1 end_page = 5 # 循环遍历每一页的房源列表页 for page in range(start_page, end_page + 1): url = f'https://{city}.lianjia.com/zufang/pg{page}/#contentList' response = requests.get(url, headers=headers) soup = BeautifulSoup(response.text, 'html.parser') # 解析房源信息 house_list = soup.find_all('div', class_='content__list--item--main') for house in house_list: district = house.find('a', class_='content__list--item--des').text.strip() street = house.find('a', class_='content__list--item--des').find_next('a').text.strip() community = house.find('a', class_='content__list--item--des').find_next('a').find_next('a').text.strip() floor = house.find('span', class_='content__list--item--des').text.strip() lift = house.find('span', class_='content__list--item--des').find_next('span').text.strip() area = house.find('span', class_='content__list--item--des').find_next('span').find_next('span').text.strip() toward = house.find('span', class_='content__list--item--des').find_next('span').find_next('span').find_next('span').text.strip() model = house.find('span', class_='content__list--item--des').find_next('span').find_next('span').find_next('span').find_next('span').text.strip() rent = house.find('span', class_='content__list--item-price').text.strip() # 打印房源信息 print(f"城区名:{district}") print(f"街道名:{street}") print(f"小区名:{community}") print(f"楼层信息:{floor}") print(f"有无电梯:{lift}") print(f"面积:{area}") print(f"房屋朝向:{toward}") print(f"户型:{model}") print(f"租金:{rent}") print("") ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值