Python爬虫之路(9)--an居客数据获取

安居客房价获取

一、前言

在前文当中,我们学习了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三连。

相关推荐
iracole1 小时前
深度学习训练Camp:第R5周:天气预测
人工智能·python·深度学习
梦丶晓羽3 小时前
自然语言处理:最大期望值算法
人工智能·python·自然语言处理·高斯混合模型·最大期望值算法
君科程序定做4 小时前
PDFMathTranslate安装使用
python
Linzerox5 小时前
Pycharm 取消拼写错误检查(Typo:in word xxx)
python·pycharm
千里码aicood5 小时前
[含文档+PPT+源码等]精品基于Python实现的校园小助手小程序的设计与实现
开发语言·前端·python
Icomi_6 小时前
【神经网络】0.深度学习基础:解锁深度学习,重塑未来的智能新引擎
c语言·c++·人工智能·python·深度学习·神经网络
蠟筆小新工程師6 小时前
Deepseek可以通过多种方式帮助CAD加速工作
开发语言·python·seepdeek
NoBarLing6 小时前
python将目录下的所欲md文件转化为html和pdf
python·pdf·html
岱宗夫up7 小时前
【Python】Django 中的算法应用与实现
数据库·python·opencv·django·sqlite
天道有情战天下8 小时前
python flask
开发语言·python·flask