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三连。

相关推荐
大佬,救命!!!18 分钟前
整理python快速构建数据可视化前端的Dash库
python·信息可视化·学习笔记·dash·记录成长
孔丘闻言20 分钟前
python调用mysql
android·python·mysql
Teletele-Lin39 分钟前
Miniconda安装与VSCode搭建远程Python、Jupyter开发环境
vscode·python·jupyter·环境配置·远程开发
伊玛目的门徒1 小时前
告别 OpenAI SDK:如何使用 Python requests 库调用大模型 API(例如百度的ernie-4.5-turbo)
python·openai·requests·大模型调用·ernie-4.5-turbo
sinat_602035362 小时前
模块与包的导入
运维·服务器·开发语言·python
计算机学姐2 小时前
基于Python的旅游数据分析可视化系统【2026最新】
vue.js·后端·python·数据分析·django·flask·旅游
恋雨QAQ2 小时前
python函数和面向对象
开发语言·python
天雪浪子3 小时前
Python入门教程之逻辑运算符
开发语言·python
张子夜 iiii3 小时前
实战项目-----在图片 hua.png 中,用红色画出花的外部轮廓,用绿色画出其简化轮廓(ε=周长×0.005),并在同一窗口显示
人工智能·pytorch·python·opencv·计算机视觉