Python采集爬取cnmo网站手机数据案例实现

news2024/9/21 18:51:06

前言

本例子利用Python爬虫爬取cnmo网站2020年至2022年11月的手机数据,并对其进行数据处理和可视化分析。

1、效果展示

如下如最终我们将得到一个包含手机型号、颜色、内存、价格及购买链接等的excel表以及dataframe和可视化效果。

2、需要用到的库

import pandas as pd
import numpy as np

import requests
from bs4 import BeautifulSoup
from lxml import etree

import matplotlib.pyplot as plt

第一个库是数据分析处理的库

第二个是数组计算

第三个是爬虫请求库

  • 五个是网页解析

第六个是图形可视化库

3、原理分析

这个大部分原理都很简单。

  1. 观察列表页的链接地址的规律,并运用dataframe存储每一款手机的参数链接以及手机型号等。

2、获取dataframe中的每个手机的参数链接

3、获取每一款手机的所有颜色和内存等所有组合的数据,并存为同一个dataframe,这里运行非常久,毕竟先读取页面获取每个手机的参数链接,在读取每一个参数链接爬取里面的参数,存为dataframe,一来一回很耗内存,所以后面最好把dataframe存为csv等格式,方便处理数据。

4、将获得的dataframe存为csv方便后期处理数据和可视化

5、最后就是读取csv的数据了,用了pandas中的一些方法,读出来的也是dataframe格式,通过pandas方法,进行转换格式,统计计算,最后通过matloplit可视化。

4、代码实现

先获取参数页和标题也就是下图网页中的内容

通过网页定位可以找到手机型号和参数链接的网页代码,方便我们后面用beautifulsoup和etree进行解析定位爬取手机型号和发布时间、参数链接,存为dataframe

具体代码如下:

url='https://product.cnmo.com/all/product_t1_p{}.html'
def lianjie():
    colum_name = ['标题', '时间', '链接']
    data_list = []
    for i in range(1,20):#翻页,20页
        url_lj=url.format(i)
        header = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}
        res=requests.get(url_lj,header).text
        soup=BeautifulSoup(res,'lxml')
        for b in soup.find('ul',class_="all-con-con-ul cf").find_all('li'):
            temp = []
            title=b.find('a',class_="name").text
            time=b.find('p',class_="red").find('span').text.replace(' ','').replace('\n','')
            url_canshu='https:'+b.find('div',class_="info").select('a')[1].get('href')
            temp.append(title)
            temp.append(time)
            temp.append(url_canshu)
            data_list.append(temp)

    data = pd.DataFrame(data_list, columns=colum_name)
    return data

如上图获得手机型号和发布时间等数据,存为dataframe,但是我们还要接着存其他的参数信息,所以定义一个函数先创建要存储的dataframe的列名称。具体代码如下:

def chuli(data):
    data1=data.dropna(thresh=2)
    data1.drop_duplicates(subset=['标题'])
    data1['nian']=(data1['时间'].str.split('年',expand=True)[0]).astype('int')
    data1['yue'] = ((data1['时间'].str)[-3:-1]).astype('int')
    data1=data1.loc[((data1['nian']>=2020)&(data1['nian']<2023)),:]
    data1=data1.loc[~((data1['nian']==2022)&(data1['yue']==12)),:]
    data1['品牌']=''#列号5
    data1['型号']=''
    data1['尺寸']=''
    data1['价格']=''
    data1['手机内存'] = data1['标题'].str.split('(', expand=True)[1]
    data1['手机内存']=data1['手机内存'].str.split(')', expand=True)[0]
    data1['cpu']=''
    data1['相机像素']=''
    data1['颜色']=''

    return data1

接下来的话,就是把dataframe里面的每一个参数链接提取出来,通过request请求获得该链接里面的手机品牌、内存、颜色、像素、尺寸等参数信息,并且存为同一个dataframe,这里面用到了beautifulsoup和etree去解析定位所要爬的参数,最后将dataframe存储为csv格式,如下图:

实现代码如下:

def canshu(data1):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}
    for j in range(data1.shape[0]):
        r=requests.get(data1.iloc[j,2],headers=headers).text
        b=etree.HTML(r)
        c=BeautifulSoup(r,'lxml')
        data1.iloc[j,5]=b.xpath('/html/body/div[5]/div[2]/a[3]/text()')
        data1.iloc[j,6]=b.xpath('/html/body/div[5]/div[4]/div[1]/div[1]/div[1]/h2/b/a/text()')
        try:
            data1.iloc[j,7]=c.find('div',class_="cell-con-ul").find_all('ul')[2].find('p',paramname="屏幕尺寸").text.replace('\n','').replace(' ','').replace('\r','')

            data1.iloc[j,8]=b.xpath('/html/body/div[5]/div[4]/div[1]/div[1]/div[2]/span[2]/text()')

            data1.iloc[j,10]=c.find('div',class_="cell-con-ul").find_all('ul')[3].find('p',paramname="CPU型号").text.replace('\n','').replace(' ','').replace('\r','')
            data1.iloc[j,11]=c.find('div',class_="cell-con-ul").find_all('ul')[4].find('p',paramname="后置相机").text.replace('\n','').replace(' ','').replace('\r','')

            data1.iloc[j,12]=c.find('div',class_="cell-con-ul").find_all('ul')[1].find('p',paramname="手机颜色").text.replace('\n','').replace(' ','').replace('\r','')
        except:
            pass
    data1.to_csv('手机各品牌机型数据.csv',index=False)  # 保存数据到CSV文件
    print("第",j,"页")
    return data1

最后一个步骤就是可视化,要可视化先要读取数据,为了节省运行时间,先把存为csv格式的数据提取出来,存为dataframe,然后在去处理各个字段,比如把内存处理,如12+256GB这个数据处理成手机内存和物理内存两种,如果没有物理内存或者手机内存的设置为0,如果出现1TB这种,直接给1024GB;还有时间的处理,将年和月分别拆成按年和按月两个字段,方便去做季度统计;还有将尺寸处理成浮点型数据,方便后期去计算,里面用到的都是pandas的方法。当处理好之后,就可以使用matloplit进行可视化了,如下图处理好的数据和可视化效果。

具体代码如下:

import pandas as pd
import numpy as np
data=pd.read_csv('手机各品牌机型数据.csv',encoding='gbk')
data1=data.dropna(thresh=12)
data1['尺寸']=(data1['尺寸'].str.split('英寸',expand=True)[0]).astype('float')
data1['手机内存']=data1['手机内存'].str.split('G',expand=True)[0]
data1['物理内存']=data1['手机内存'].str.split('+',expand=True)[1]

data1['手机内存']=(data1['手机内存'].str.split('+',expand=True)[0])

data1=data1.dropna(thresh=13)
data1['季度']=None
for i in range(data1.shape[0]):
    if data1.iloc[i,9]=='1TB':
        data1.iloc[i, 9]='1024'
    if int(data1.iloc[i,9])>16:
        data1.iloc[i,13]=data1.iloc[i,9]
    if data1.iloc[i,13] is None:
        data1.iloc[i, 13]='0'
    if data1.iloc[i,13]=='':
        data1.iloc[i, 13] = '0'
    else:
        pass
data1['手机内存']=data1['手机内存'].astype('int')
data1['物理内存']=data1['物理内存'].astype('int')
for j in range(data1.shape[0]):
    if data1.iloc[j, 9]>16:
        data1.iloc[j, 9]=0
    if data1.iloc[j, 9]==1:
        data1.iloc[j, 9]==0
    if 0<data1.iloc[j,4]<4:
        data1.iloc[j,14]='第一季度'
    if 3<data1.iloc[j,4]<7:
        data1.iloc[j,14]='第二季度'
    if 6<data1.iloc[j,4]<10:
        data1.iloc[j,14]='第三季度'
    if 9<data1.iloc[j,4]<13:
        data1.iloc[j,14]='第四季度'
    else:
        pass
# data1 = data1.loc[((data1['手机内存'] >1) & (data1['手机内存'] <=16)), :]
print(data1)
print("所有手机的平均尺寸是:",data1['尺寸'].mean())
data2=data1.groupby(by=['yue'])['尺寸'].mean().reset_index().round(2)#统计月份平均尺寸
data3=data1.groupby(by=['季度'])['尺寸'].mean().reset_index().round(2)#统计季度平均尺寸
data4=data1.groupby(by=['品牌'])['尺寸'].mean().reset_index().round(2)#统计品牌平均尺寸
data1['价格']=data1['价格'].astype('int')
list_jiage=[]
data5=(data1.loc[((data1['价格']>=1000)&(data1['价格']<2000)),:])['尺寸'].mean().round(2)
data6=(data1.loc[((data1['价格']>=2000)&(data1['价格']<3000)),:])['尺寸'].mean().round(2)
data7=(data1.loc[((data1['价格']>=3000)&(data1['价格']<4000)),:])['尺寸'].mean().round(2)
data8=(data1.loc[((data1['价格']>=4000)&(data1['价格']<5000)),:])['尺寸'].mean().round(2)
data9=(data1.loc[((data1['价格']>=5000)&(data1['价格']<6000)),:])['尺寸'].mean().round(2)
data10=(data1.loc[((data1['价格']>=6000)&(data1['价格']<7000)),:])['尺寸'].mean().round(2)
data11=(data1[data1['价格']>=7000])['尺寸'].mean().round(2)
list_jiage.append(data5)
list_jiage.append(data6)
list_jiage.append(data7)
list_jiage.append(data8)
list_jiage.append(data9)
list_jiage.append(data10)
list_jiage.append(data11)
list_jiage1=['价格大于1000小于2000','价格大于2000小于3000','价格大于3000小于4000','价格大于4000小于5000','价格大于6000小于6000','价格大于6000小于7000','价格大于7000']

print(list_jiage)

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 解决中文显示问题
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
# 生成图形
plt.plot(data3['季度'], data3['尺寸'], 'go:', label='尺寸变化', linewidth=2) # 颜色绿色,点形圆形,线性虚线,设置图例显示内容,线条宽度为2
for a, b in zip(data3['季度'], data3['尺寸']):
    plt.text(a, b, b, ha='center', va='bottom', fontsize=20)
plt.ylabel('尺寸') # 横坐标轴的标题
plt.xlabel('季度') # 纵坐标轴的标题
plt.xticks(np.arange(0, 4, 1)) # 设置横坐标轴的刻度为 0 到 4的数组
plt.ylim([0, 10]) # 设置纵坐标轴范围为 -2 到 2
plt.legend() # 显示图例, 图例中内容由 label 定义
plt.grid() # 显示网格
plt.title('各个季度手机平均尺寸') # 图形的标题

# 显示图形
plt.show()

#定义函数来显示柱子上的数值
def autolabel(rects):
    for rect in rects:
        height = rect.get_height()
        plt.text(rect.get_x()+rect.get_width()/2.-0.08, 1.03*height, '%s' % height, size=6, family="Times new roman")

plt.figure(figsize=(4,3))

cm = plt.bar(data4['品牌'], data4['尺寸'], width=0.5, color=["blue", "green", "yellow", "magenta"])
autolabel(cm)

plt.ylim((0, 10))
plt.xlabel("品牌", size=12)
plt.ylabel("尺寸", size=12)
plt.xticks(rotation=90)
plt.title('各个品牌手机平均尺寸')
plt.show()

plt.plot(list_jiage1, list_jiage, 'go:', label='尺寸变化', linewidth=2) # 颜色绿色,点形圆形,线性虚线,设置图例显示内容,线条宽度为2
for a, b in zip(list_jiage1, list_jiage):
    plt.text(a, b, b, ha='center', va='bottom', fontsize=20)
plt.ylabel('尺寸') # 横坐标轴的标题
plt.xlabel('不同价格区间') # 纵坐标轴的标题
plt.xticks(rotation=90) # 设置横坐标轴的刻度为 0 到 4的数组
plt.ylim([0, 10]) # 设置纵坐标轴范围为 -2 到 2
plt.legend() # 显示图例, 图例中内容由 label 定义
plt.grid() # 显示网格
plt.title('不同价格区间的手机平均尺寸') # 图形的标题
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2037341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【OpenCV——python】形态学变换 颜色空间 颜色替换 掩膜 旋转

形态学变换 形态学变换一般是处理二值图的腐蚀和膨胀操作&#xff0c;输入二值化图像和核&#xff0c;对图像进行类似卷积的操作 核 核是一定大小的区域&#xff0c;在原图中进行滑动计算 腐蚀erode 腐蚀过程 核在图像上滑动&#xff0c;对应位置相乘&#xff0c;最小值作为核…

孙宇晨领航波场TRON:引领数字资产迈向崭新纪元

​ 在风起云涌的数字资产领域&#xff0c;孙宇晨这个名字始终与创新、突破和引领紧密相连。作为波场TRON的创始人&#xff0c;他不仅是一位远见卓识的领导者&#xff0c;更是推动数字资产迈向新纪元的坚实力量。 自波场TRON诞生以来&#xff0c;孙宇晨便以其敏锐的洞察力…

MongoDB教程

目录 介绍启动命令命令行操作常用命令总结MongoDB Compass 介绍 MongoDB是一个基于分布式文件存储的开源数据库系统&#xff0c;由C语言编写&#xff0c;旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB将数据存储为一个文档&#xff0c;数据结构由键值对组成&…

轮式遥控无人侦察车技术详解

轮式遥控无人侦察车&#xff08;Wheeled Remote-Controlled Unmanned Ground Vehicle, RCUGV&#xff09;作为现代战场及复杂环境侦察作业的重要工具&#xff0c;以其灵活性高、机动性强、风险低等优势&#xff0c;在军事侦察、灾害评估、环境监测等多个领域发挥着不可替代的作…

Cesium 加载高斯泼溅(Gaussian Splatting)模型

Cesium 加载高斯泼溅&#xff08;Gaussian Splatting&#xff09;模型 高斯泼溅&#xff08;Gaussian Splatting&#xff09; 高斯泼溅是一种革命性的 3D 重建新方法&#xff0c;它试图解决其他方法存在的一些问题&#xff0c;例如处理时间长。对于这种方法&#xff0c;他们的…

成都云飞浩容文化传媒有限公司是做什么的?

在数字经济的浪潮中&#xff0c;电商行业如日中天&#xff0c;成为推动经济发展的重要引擎。在这场没有硝烟的商战中&#xff0c;如何脱颖而出&#xff0c;实现品牌与销量的双重飞跃&#xff1f;成都云飞浩容文化传媒有限公司&#xff0c;作为电商服务领域的佼佼者&#xff0c;…

JavaHadoop白云白云图书管理系统---附源码19272

目 录 摘要 Abstract 1 绪论 1.1 研究背景及意义 1.2国内外研究现状 1.3 论文结构与章节安排 2 白云图书管理系统系统分析 2.1 系统可行性分析 3.2.1 技术可行性 3.2.2 经济可行性 3.2.3 操作可行性 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 …

【Web】LIT CTF 2024 题解(全)

目录 anti-inspect jwt-1 jwt-2 traversed kirbytime scrainbow anti-inspect 因为一直while true&#xff0c;网页会卡死无法访问 const flag "LITCTF{your_%cfOund_teh_fIg_94932}";console.log(flag,"background-color: darkblue; color: white; f…

Nginx异常关闭之中了挖矿病毒kswapd0

问题描述&#xff1a;系统突然无法访问了&#xff0c;登录服务器看了一下是因为Nginx服务关闭&#xff0c;重启后过了几天仍然异常关闭 系统&#xff1a;CentOS 7&#xff0c;Nginx 1.20 尝试解决过程&#xff1a;1、查询nginx/logs/error.log、系统日志&#xff0c;都没有查…

Ubuntu18.04 配置EtherCAT主站IGH SOEM

IGH IGH 是开源的EtherCAT 主站软件 一、安装依赖 sudo apt update sudo apt install build-essential linux-headers-$(uname -r) mercurial autoconf libtool 也不知道安装的完全不完全 uname -r 可以查看内核&#xff0c;我安装的ubuntu18.04的内核版本是 5.4.0-84-gen…

Robotics: Aerial Robotics 部分笔记——Week2(1) 运动学

Week 2.1 g ( q ) g(q) g(q) is called g of q.Rotation matrix R R R: P ′ R P PRP P′RP。旋转矩阵都是正交的&#xff08;orthogonal&#xff09;&#xff0c;即 R T R R R T I R^TRRR^TI RTRRRTI&#xff1b;行列式为1 d e t R 1 det R 1 detR1&#xff1b;且旋转矩…

【JAVA】阿里巴巴的Arthas:Java应用诊断的利器

文章目录 引言1. Arthas概述2. 安装与配置3. 基本使用4. 业务开发示例5. 高级功能6. 实践经验与案例分析7. 结论8. 附录 更多相关内容可查看 引言 在现代软件开发中&#xff0c;Java作为一种广泛使用的编程语言&#xff0c;承担着大量企业级应用的开发任务。然而&#xff0c;随…

Linux驱动入门实验班——Hello驱动(后附百问网课程视频链接)

目录 1.如何编写驱动程序 2.编写驱动程序 ①确定主设备号 register_chrdev函数 ②file_operations结构体 ③实现对应的函数&#xff0c;填入结构体 copy_from_user函数 copy_to_user函数 ④注册驱动程序 方式一 方式二 ⑤入口函数 ⑥出口函数 ⑦提供设备信息&#x…

Type-C接口取电芯片-LDR6500

取电芯片&#xff0c;特别是针对Type-C接口的取电芯片&#xff0c;如LDR6328系列&#xff0c;是近年来电子设备领域的一个重要技术组件。这些芯片通过智能协议控制&#xff0c;实现高效、安全的充电过程&#xff0c;并广泛应用于智能手机、平板电脑、笔记本电脑、小家电等各类需…

18. 基于ES实战海量数据检索

18. 基于ES实战海量数据检索 一. 概述二. Elasticsearch 全文检索1. 分布式搜索引擎2. 搜索引擎种类3. 倒排索引三. elastic使用1. 官网介绍2. docker安装3. elasticsearch-head工具4. 分词与内置分词4.1 内置分词器(了解即可)4.2 `IK`中文分词器*****************************…

打造高效信息发布平台小程序:设计思路与实践

在当今这个信息爆炸的时代&#xff0c;信息发布平台已成为连接用户与内容的桥梁&#xff0c;小程序以其独特的优势成为众多企业和个人开发者青睐的选择。开发一款专注于信息发布与共享的小程序&#xff0c;旨在为用户打造一个便捷、高效、互动性强的信息获取平台&#xff0c;具…

使用docker-compose快速部署Prometheus+grafana环境

初始化 Prometheusgrafana 创建相关目录并给予权限&#xff0c;持久化目录需要给777权限&#xff0c;否则容器启动失败 cd ~ && mkdir prometheus && chmod 777 prometheus cd prometheus && mkdir grafana_data prometheus_data && chmod 777…

过滤器实验

1.过滤器实验 首先写两个页面之间能够互相跳转 Test1.html通过超链接跳转到test2.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <!--&l…

LDR6020在Type-C手机同时充电与USB2.0数据传输方案

随着科技的飞速发展&#xff0c;Type-C接口已成为智能手机等移动设备的主流充电和数据传输接口。为了满足用户对于高效充电与稳定数据传输的双重需求&#xff0c;乐得瑞科技推出的LDR6020芯片凭借其卓越的性能和丰富的功能&#xff0c;为Type-C手机提供了同时充电与USB2.0数据传…

欢迪迈手机商城设计与开发

TOC springboot137欢迪迈手机商城设计与开发 绪论** 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0…