第一次的爬取老师说可能不够好,这的那的,那就再来一次呗。

她推荐我们爬取武汉二手房的房价,因为里面的信息比较全。

红色圈出来的都需要爬,这老师,有点坑。

局限比较大,只能存放一页的数据,因为这个网站反扒有点恶心,不想搞了,而且获取一页的数据也够了,多了反而数据不好展示。

python爬取咸鱼商品信息 python能爬取闲鱼最新吗_html

代码在最后面,直接展示可视化界面和保存的Excel数据了。

  • 标题:就是黑色的大标题
  • 价格:这个是总的价格,单位万元
  • 地点:这个是主要作为可视化图像界面的x轴的,因为字比较短,标题太长了
  • 布局:几室几厅的
  • 具体位置:字面意思,具体位置
  • 面积:这个直接获取的int类型的数字,因为要界面处理,只能获取数字
  • 楼层:就是楼层
  • 楼层数:就是楼层数
  • 年份:有的就获取,没有的就是null

python爬取咸鱼商品信息 python能爬取闲鱼最新吗_爬虫_02

python爬取咸鱼商品信息 python能爬取闲鱼最新吗_html_03

python爬取咸鱼商品信息 python能爬取闲鱼最新吗_开发语言_04

提前说一下,如果获取的内容都是空的,那就直接去网站上刷新一下,因为有个机制,但时候就知道了。

#Time : 2022-11-26
#Actor: WangDengtao
#Contents: Wuhan second-hand house information crawl

import requests
import bs4
import pandas as pd
import numpy as np
import time
import matplotlib.pyplot as plt
import xlwt
import re
import squarify

#解决乱码问题,显示中文标签
plt.rcParams['font.sans-serif']=['SimHei'] 
plt.rcParams['axes.unicode_minus']=False


#获取地点函数
#------------------------------------------------------------
def get_title(html):
    title_buf = []
    soup = bs4.BeautifulSoup(html.content, 'html.parser')
    for dl in soup.find_all('dl',{'class':'clearfix'}):
        title_f = dl.span.string
        
        #去除‘\n’'\t',获取地址
        title_a = list(title_f)
        title_b = title_a[13:]
        
        #合并列表中的各元素组成地名
        title = ''.join(title_b)
        
        title_buf.append(title)
    return title_buf



#获取价格函数
#------------------------------------------------------------
def get_price(html):
    price_buf = []
    soup = bs4.BeautifulSoup(html.content, 'html.parser')
    for dd in soup.find_all('dd',{'class':'price_right'}):
        price_f = dd.b.string

        price_f = int(price_f)
        price_buf.append(price_f)
    return price_buf



#获取地点函数
#------------------------------------------------------------
def get_addr(html):
    addr_buf = []
    soup = bs4.BeautifulSoup(html.content, 'html.parser')
    for p in soup.find_all('p',{'class':'add_shop'}):
        addr_f = p.a.string
        
        #去除‘\n’'\t',获取地址
        addr_a = list(addr_f)
        addr_b = addr_a[12:-11]
        
        #合并列表中的各元素组成地名
        addr = ''.join(addr_b)
        
        addr_buf.append(addr)
    return addr_buf



#获取具体地址函数
#------------------------------------------------------------
def get_location(html):
    location_buf = []
    soup = bs4.BeautifulSoup(html.content, 'html.parser')
    for p in soup.find_all('p',{'class':'add_shop'}):
        location_f = p.span.string
        
        location_buf.append(location_f)
    return location_buf



#获取X室X厅
#------------------------------------------------------------
def get_all_a(a):

    all_a_buf = []

    a1 = list(a)
    #print(a1[0])
    a2 = list(a1[0])
    a3 = a2[11:-23]
    a4 = ''.join(a3)
    #print(a4)
    all_a_buf.append(a4)
    
    return all_a_buf



#获取房屋面积
#------------------------------------------------------------
def get_all_b(a):

    all_b_buf = []
    a1 = list(a)
    a2 = list(a1[2])
    a2 = [item for item in a2 if item not in ['\n', '\t']]
    a3 = a2[0:-1]
    #print(a2)
    a4 = ''.join(a3)
    #print(a3)
    a4 = float(a4)
    all_b_buf.append(a4)
    
    return all_b_buf



#获取房屋楼层
#------------------------------------------------------------
def get_all_c(a):
    all_c_buf = []

    a1 = list(a)
    #print(a1)
    a2 = list(a1[5])
    #print(a2)
    a3 = ''.join(a2)
    if a3 not in ['中层', '高层','低层','顶层']:
        a2 = list(a1[4])
        #print(a2)
        a4 = a2[25:-63]
        #print(a4)
        a3 = ''.join(a4)
        
        
    #print(a3)
    all_c_buf.append(a3)
    
    return all_c_buf



#获取房屋楼层数
#------------------------------------------------------------
def get_all_d(a):
    all_d_buf = []

    a1 = list(a)
    #print(a1)
    a2 = list(a1[6])
    
    a3 = [item for item in a2 if item not in ['\n', '\t']]
    a5 = ''.join(a3)
    if a5 in['南向','北向','西向','东向','东南向','东北向','西南向','西北向','南北向','东西向']:
        a2 = list(a1[4])
        #print(a2)
        a3 = a2[51:-34]
        #print(a6)
        
    #print(a2)
    a4 = ''.join(a3)
    a7 = list(a4)
    a8 = a7[2:-2]
    a4 = ''.join(a8)
    a4 = int(a4)
    all_d_buf.append(a4)
    
    return all_d_buf



#获取房屋建造年份
#------------------------------------------------------------
def get_all_e(a):
    all_e_buf = []

    a1 = list(a)
    #print(a1)
    a2 = list(a1[-1])
    
    a3 = [item for item in a2 if item not in ['\n', '\t']]
                 
    #print(a2)
    a4 = ''.join(a3)
    if a4 in ['南向','北向','西向','东向','东南向','东北向','西南向','西北向','南北向','东西向']:
        a4 = 'null'
    all_e_buf.append(a4)
    
    return all_e_buf



#画柱状图(地址+房价(单位万))
#------------------------------------------------------------
def picture2(all_price, all_addr):
    x_data = all_addr;
    y_data = all_price;

    # 画图,plt.bar()可以画柱状图
    for i in range(len(x_data)):
        plt.bar(x_data[i], y_data[i])

    # 设置x轴标签名
    plt.xlabel("地点")
    #设置刻度标记的大小,设置刻度的样式
    plt.xticks(rotation = -90,size = 10)
    #设置位置,方便看的
    plt.subplots_adjust(left=0.05, bottom=0.297, right=0.962, top=0.95)
    # 设置y轴标签名
    plt.ylabel("价格(万)")
    # 显示
    plt.show()
    


#面积分布图(地址+面积)
#------------------------------------------------------------
def picture3(size, all_addr,indoor_planning):
    plt.rcParams['font.sans-serif'] = 'Microsoft YaHei'
    plt.rcParams['axes.unicode_minus'] = False
    自定义颜色 = ['r', 'y', 'b', 'g', 'yellow', 'cyan', 'coral']
    图 = squarify.plot(sizes = size,
                      label=all_addr,# 指定标签
                      color=自定义颜色,  # 自定义颜色
                      alpha=0.6,
                      value=indoor_planning, # 添加数据标签
                      edgecolor='white',  # 设置边界框颜色为白色
                      linewidth=3,  # 设置边框宽度
                      text_kwargs={'fontsize': 9})  # 设置字体大小
    图.set_title("房屋面积及房屋规划", fontdict={'fontsize': 20})
    plt.axis('off')  # 去掉坐标轴
    plt.tick_params(top='off', right='off')  # 去掉刻度
    plt.show()
    


#分组柱状图(价格+面积+地点)
#------------------------------------------------------------
def picture4(size, all_price, all_addr):
    # 设置标题
    plt.title('价格面积分组柱状图')
    #数据准备
    x = all_addr
    y1= all_price
    y2= size
    #设置图形宽度
    bar_width = 0.3
    X_A = np.arange(len(x))  # A班条形图的横坐标
    X_B = X_A + bar_width  # B班条形图的横坐标
    #绘制图形
    plt.bar(X_A,y1,bar_width,align='center',color='r')
    #并列柱状图:x轴加上宽度
    plt.bar(X_B,y2,width=bar_width,color='y')
    plt.xticks(X_A + bar_width/2, x)# 让横坐标显示运动
    #加图例
    plt.legend(['价格(万)','面积(m3)'])
    plt.ylabel('价格(万)面积(m3)')  # 纵坐标轴标题
    fig=plt.gcf()
    #设置刻度标记的大小,设置刻度的样式
    plt.xticks(rotation = -90,size = 10)
    #设置位置,方便看的
    plt.subplots_adjust(left=0.05, bottom=0.215, right=0.962, top=0.95)
    #显示
    plt.show()

    
#楼层分布图(楼层+层数+建造年份)
#------------------------------------------------------------
def picture5(floor, floors,year):
    plt.rcParams['font.sans-serif'] = 'Microsoft YaHei'
    plt.rcParams['axes.unicode_minus'] = False
    自定义颜色 = ['r', 'y', 'b', 'g', 'yellow', 'cyan', 'coral']
    图 = squarify.plot(sizes = floors,
                      label=floor,# 指定标签
                      color=自定义颜色,  # 自定义颜色
                      alpha=0.6,
                      value=year, # 添加数据标签
                      edgecolor='white',  # 设置边界框颜色为白色
                      linewidth=3,  # 设置边框宽度
                      text_kwargs={'fontsize': 9})  # 设置字体大小
    图.set_title("楼层及其建造年份", fontdict={'fontsize': 20})
    plt.axis('off')  # 去掉坐标轴
    plt.tick_params(top='off', right='off')  # 去掉刻度
    plt.show()

        
    

#保存数据到EXCEL函数
#------------------------------------------------------------
def save_excel(all_price, all_addr,all_title,indoor_planning,all_location,size,floor,floors,year):
    # 创建工作workbook
    workbook = xlwt.Workbook()
    
    # 创建工作表worksheet,填入表名
    worksheet = workbook.add_sheet('Wuhan_House_Price_Table')

    # 在表中写入相应的数据
    worksheet.write(0, 0, '标题')
    worksheet.write(0, 1, '价格(万)')
    worksheet.write(0, 2, '地点')
    
    worksheet.write(0, 3, '布局')
    worksheet.write(0, 4, '具体位置')
    worksheet.write(0, 5, '面积(m2)')
    worksheet.write(0, 6, '楼层')
    worksheet.write(0, 7, '楼层数')
    worksheet.write(0, 8, '建造年份')
    
    for i in range(len(all_price)):
        worksheet.write(1+i, 0, all_title[i])       
        worksheet.write(1+i, 1, all_price[i])
        worksheet.write(1+i, 2, all_addr[i])
        
        worksheet.write(1+i, 3, indoor_planning[i])
        worksheet.write(1+i, 4, all_location[i])
        worksheet.write(1+i, 5, size[i])
        worksheet.write(1+i, 6, floor[i])
        worksheet.write(1+i, 7, floors[i])
        worksheet.write(1+i, 8, year[i])
               

    # 保存表
    workbook.save('F:\course\python\science\Wuhan_housing_price_Trend.xls')
    print('数据存入EXCEL成功!')
    


#主函数开始
#------------------------------------------------------------
    
url = ("https://wuhan.esf.fang.com/house/a21-i33/?rfss=1-3c99878a26acceb41e-6c")
#存放全部价格
all_price = []
#存放全部地点
all_addr = []
#存放全部标题
all_title = []
#存放全部地址
all_location = []
#存放小标签的地方
all_a = []
#存放x室X厅
indoor_planning = []
#存放房屋大小
size = []
#存放楼层
floor = []
#楼层数
floors = []
#房屋建造年份
year = []


for i in range(1,2):
    try:
        html = requests.get(url)
        html.raise_for_status()
        html.encoding = 'utf-8'
            
        #将获取的网页代码生成TXT文件
        path = 'E:\\评论第{}页.txt'.format(i)
        with open(path, 'w', encoding = 'utf-8') as file:
            file.write(html.text)

        #获取标题
        page_title = get_title(html)
        all_title.extend(page_title)
        #print(all_title)

        #获取价格
        page_price = get_price(html)
        all_price.extend(page_price)
        #print(all_price)

        #获取地点
        page_addr = get_addr(html)
        all_addr.extend(page_addr)
        #print(all_addr)

        #获取具体地址
        page_location = get_location(html)
        all_location.extend(page_location)
        #print(all_location)

        #获取X室X厅、X平方米、楼层、楼层数、朝向、X年建
        soup = bs4.BeautifulSoup(html.content, 'html.parser')
        for dl in soup.find_all('dl',{'class':'clearfix'}):
            a = dl.find('p',{'class':'tel_shop'})

            
            #调用get_all_a()获取X室X厅存放在indoor_planning中
            page_indoor_planning = get_all_a(a)
            indoor_planning.extend(page_indoor_planning)

            #调用get_all_b()获取房屋面积存放在size中
            page_size = get_all_b(a)
            size.extend(page_size)

            #调用get_all_c()获取房屋面积存放在floor中
            page_floor = get_all_c(a)
            floor.extend(page_floor)
            
            #调用get_all_d()获取房屋面积存放在floors中
            page_floors = get_all_d(a)
            floors.extend(page_floors)

            #调用get_all_d()获取房屋面积存放在floors中
            page_year = get_all_e(a)
            year.extend(page_year)

            
        #print(indoor_planning)
        #print(size)
        #print(floor)
        #print(floors)

        #保存到Excel中
        save_excel(all_price, all_addr,all_title,indoor_planning,all_location,size,floor,floors,year)

        #展示可视化图片
        picture2(all_price, all_addr)
        picture3(size, all_addr,indoor_planning)
        picture4(size, all_price, all_addr)
        picture5(floor, floors,year)
        
        
        print("完成第{}页".format(i))
        time.sleep(3)

    except Exception as ex:
        print("第{}页采集出错,出错原因:{}".format(i, ex))

想想后面用PowerBI又将数据整理了一下,感觉房价的确实难分析,因为地点太多了。

python爬取咸鱼商品信息 python能爬取闲鱼最新吗_python爬取咸鱼商品信息_05

python爬取咸鱼商品信息 python能爬取闲鱼最新吗_开发语言_06

python爬取咸鱼商品信息 python能爬取闲鱼最新吗_开发语言_07

都有注释,具体字符串怎么处理的就不说了,直接用吧。