安居客房价获取
一、前言
在前文当中,我们学习了xpath解析,本文讲利用xpath对安居客的房价进行数据提取的解析。
目标url: https://cs.anjuke.com/sale/yuelu/
二、数据分析
牢记爬虫开发三步骤
1.数据位置分析
2.数据获取
3.数据清洗与展示
①:打开页面源代码,查看一下内容是否在源代码中
可以发现,文章内容就写在源代码里面的,那么我们直接根据页面的url发送get请求就可以获取到(get请求一般不需要提交表单,所以可以直接通过url打开的大部分为get请求)。
别忘了,设置请求头U-A参数,进行简单的反 反爬 手段。
code如下:
ruby
class House(object):
def __init__(self):
self.headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.54'
}
def parse_url(self):
url='https://cs.anjuke.com/sale/yuelu/'
resp = requests.get(url,headers=self.headers)
三、数据清洗与展示
①数据清洗:
利用F12分析所需内容所在标签。根据下图我们可以发下我们需要的内容都在一个div标签下面,并且所有的数据都是在相同的class="property"
下面,同时我们还要注意到,只有这些数据的div标签的class值是property,所有我们可以直接使用
div_list = html.xpath('//div[@class="property"]')
来定位数据。
ps:移动到标签旁边,右键,在复制下面有 复制XPath 可以快速获取。
less
def parse_url(self):
url='https://cs.anjuke.com/sale/yuelu/'
resp = requests.get(url,headers=self.headers)
html = etree.HTML(resp.text)
div_list = html.xpath('//div[@class="property"]')
data=[]
for div in div_list:
item={}
try:
item['title'] = div.xpath('.//h3/text()')[0]
except:
item['title'] = '无标题信息'
try:
item['type'] = ''.join(div.xpath('.//p[@class="property-content-info-text property-content-info-attribute"]/span/text()'))
except:
item['type'] = '无户型信息'
try:
item['area'] = div.xpath('./a/div[2]/div[1]/section/div[1]/p[2]/text()')[0].replace('\n','').strip(' ')
except:
item['area'] = '无面积信息'
try:
item['floor'] = div.xpath('./a/div[2]/div[1]/section/div[1]/p[4]/text()')[0].replace('\n','').strip(' ')
except:
item['floor'] = '无楼层信息'
try:
item['build_time'] = div.xpath('./a/div[2]/div[1]/section/div[1]/p[5]/text()')[0].replace('\n','').strip(' ')
except:
item['build_time'] = '无建造时间信息'
try:
item['location'] = ''.join(div.xpath('./a/div[2]/div[1]/section/div[2]/p[2]//span/text()')).replace('\n','').strip(' ')
except:
item['location'] = '无位置信息'
try:
item['total_price'] =''.join(div.xpath('./a/div[2]/div[2]/p[1]//span/text()')).replace('\n','').strip(' ')
except:
item['total_price'] = '无总价信息'
try:
item['unit_price'] = div.xpath("./a/div[2]/div[2]/p[2]/text()")[0].replace('\n','').strip(' ')
except:
item['unit_price'] = '无单价信息'
print(item)
通过上面的代码,我们就可以拿到我们需要的数据了。
这时候要注意,我进行了许多的异常捕获,这是因为有时候可能有些标签是不存在的,这时候我们要捕获异常,防止程序死亡。同时还需要保证数据该有的属性的完整性。
除了我上面展示的方法,你还可以在每次item初始定义的时候,就给各个属性一个初始值,如下:
perl
item={
'title':'无标题信息',
'type':'无户型信息',
``````
'unit_price':'无单价信息',
}
try:
item['title'] = div.xpath('.//h3/text()')[0]
except:
#因为标签没有正常xpath解析到,所以任然需要捕获异常
pass
②数据展示:
需要导入的库或包
python
import pandas as pd
from pyecharts.charts import Page, Bar, Pie
from pyecharts.globals import ThemeType
import pyecharts.options as opts
保存至excel
python
def save_excel(self,data):
df = pd.DataFrame(data)
# 检查是否存在 Excel 文件,如果不存在则创建一个新的
try:
existing_df = pd.read_excel('data.xlsx')
# 将新数据追加到现有 Excel 文件中
df = pd.concat([existing_df, df], ignore_index=True)
except FileNotFoundError:
# 创建一个新的 Excel 文件
pass
df.to_excel('data.xlsx', index=False)
print("保存数据至excel成功......")
return df
绘制图像
scss
def drawing(self,df):
# 创建Page对象
page = Page(layout=Page.DraggablePageLayout)
# 第一页:房源类型分布
house_type_dist = (
Pie()
.add("", list(zip(df['type'].unique(), df['type'].value_counts().tolist())), radius=["40%", "70%"])
.set_global_opts(
title_opts=opts.TitleOpts(title="房源类型分布"),
legend_opts=opts.LegendOpts(type_="scroll", pos_left="20%", pos_right="20%"),
)
.set_series_opts(
label_opts=opts.LabelOpts(
formatter="{b}: {d}%"
)
)
)
page.add(house_type_dist)
# 第二页:总价和单价分布
total_price_dist = (
Bar()
.add_xaxis(list(df['total_price'].unique()))
.add_yaxis("", df['total_price'].value_counts().tolist())
.set_global_opts(title_opts=opts.TitleOpts(title="总价分布"))
)
unit_price_dist = (
Bar()
.add_xaxis(list(df['unit_price'].unique()))
.add_yaxis("", df['unit_price'].value_counts().tolist())
.set_global_opts(title_opts=opts.TitleOpts(title="单价分布"))
)
page.add(total_price_dist, unit_price_dist)
# 第三页:面积和楼层分布
area_dist = (
Bar()
.add_xaxis(list(df['area'].unique()))
.add_yaxis("", df['area'].value_counts().tolist())
.set_global_opts(title_opts=opts.TitleOpts(title="面积分布"))
)
floor_dist = (
Pie()
.add("", list(zip(df['floor'].unique(), df['floor'].value_counts().tolist())), radius=["40%", "70%"])
.set_global_opts(
title_opts=opts.TitleOpts(title="楼层分布"),
legend_opts=opts.LegendOpts(type_="scroll", pos_left="20%", pos_right="20%"),
)
.set_series_opts(
label_opts=opts.LabelOpts(
formatter="{b}: {d}%"
)
)
)
page.add(area_dist, floor_dist)
# 渲染多页面图表
page.render("house_data_visualization.html")
print("图像绘制成功......")
效果演示
图像会保存到同目录下的:house_data_visualization.html
利用浏览器打开即可。得到的图像可以拖动,调整大小。
四、结语
大家可以尝试去抓取这个url https://cs.lianjia.com/ershoufang/
获取第一页
数据即可,同时也可以思考一下,如何进行多页的获取,实现翻页功能。
包含的字段有:标题,位置,户型,总价,单价
......
本文当中的代码可能会有残缺,各位如果直接复制可能无法运行,可以去我的 GitHub 仓库:Python爬虫之路https://github.com/Rosyrain/spider-course
,下面的lesson9当中code下的main.py就可以查看我的源码。在源码当中,我还写了mysql,mongodb数据库以及json文件的三种存储方式,大家可以进行参考。同时欢迎大家Follow/Star/Fork ,点个star再走吧( •̀ ω •́ )✧
下一篇文章会讲解其他的解析html的方法:beautifulsoup
也叫bs4。
有任何问题欢迎大家的评论和指正。再次声明,本专栏只做技术探讨,严谨商用,恶意攻击等。
这是我的 GitHub 主页:Rosyrain (github.com) https://github.com/rosyrain
,里面有一些我学习时候的笔记或者代码。本专栏的文档和源码存到spider-course的仓库下。
欢迎大家Follow/Star/Fork三连。