当前位置:   article > 正文

基于MongoDB的气温数据可视化项目_利用python爬取天气数据并存在mongo并进行可视化处理

利用python爬取天气数据并存在mongo并进行可视化处理

本文是基于大数据方向MongoDB数据库的气温可视化项目,旨在让大家认识到MongDB数据库的使用,以及作为一个数据库该如何存储数据及取出数据,如何连接前后端,将数据展示出来。 涉及到的技术包含有Python爬虫、MongoDB的Java API,Flask框架、echarts可视化,作为一个练手小项目。

一、数据来源

编写一个爬虫程序从天气网站上爬取所需要的数据。这里爬取某市一年的天气。

爬取数据网址为:https://lishi.tianqi.com/huangshi.html,并且可以根据想要爬取的年份月份更改网址。

根据网站源代码编写爬取程序,需要注意的是,由于MongoDB的文档数据以BSON(JSON格式的一种拓展)格式存储,可以存储列表、key-value以及层次结构更加复杂的文档。我们需要将爬取到的数据添加列表中并转换成json数据文件存储,以便后续将数据存入数据库中:

爬虫代码

  1. import requests # 模拟浏览器进行网络请求
  2. from lxml import etree # 进行数据预处理
  3. import json
  4. def getWeather(uurl):
  5. weather_info = [] # 新建一个列表,将爬取的每月数据放进去
  6. # 请求头信息:浏览器版本型号,接收数据的编码格式
  7. headers = {
  8. 'User-Agent':
  9. 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 '
  10. 'Safari/537.36 Edg/118.0.2088.76'
  11. }
  12. # 请求
  13. resp = requests.get(uurl, headers=headers)
  14. # 数据预处理
  15. resp_html = etree.HTML(resp.text)
  16. # xpath提取所有数据
  17. resp_list = resp_html.xpath("//ul[@class='thrui']/li")
  18. # for循环迭代遍历
  19. for li in resp_list:
  20. day_weather_info = {'data_time': li.xpath("./div[1]/text()")[0].split(' ')[0]}
  21. # 日期
  22. # 最高气温(包含摄氏度符号)
  23. high = li.xpath("./div[2]/text()")[0]
  24. day_weather_info['high'] = high[:high.find('℃')]
  25. # 最低气温
  26. low = li.xpath("./div[3]/text()")[0]
  27. day_weather_info['low'] = low[:low.find('℃')]
  28. # 天气
  29. day_weather_info['weather'] = li.xpath("./div[4]/text()")[0]
  30. weather_info.append(day_weather_info)
  31. return weather_info
  32. weathers = []
  33. # for循环生成有顺序的1-12
  34. for month in range(1, 13):
  35. # 获取某一月的天气
  36. # 三元表达式
  37. weather_time = '2023' + ('0' + str(month) if month < 10 else str(month))
  38. print(weather_time)
  39. url = f'https://lishi.tianqi.com/huangshi/{weather_time}.html'
  40. weather = getWeather(url)
  41. weathers.append(weather)
  42. # 将列表数据存储为JSON文件
  43. with open('month_data.json', 'w') as file:
  44. json.dump(weathers, file, indent=4)
  45. print(weathers)

将爬取出来的数据转成json文件后,存储格式如下:

二、启动MongoDB数据库

环境准备(基于Hadoop集群的相关操作):

启动:myhadoop.sh start

启动:MongoDB

$/opt/module/mongodb-5.0.5/bin/mongod -f

/opt/module/mongodb-5.0.5/conf/mongo.conf

$ /opt/module/mongodb-5.0.5/bin/mongo --host 127.0.0.1 --port 27017

注意:以上启动是基于Hadoop集群上的MongoDB操作,开启虚拟机,在xshell启动。

三、将数据存储到数据库

使用爬虫获取的数据满足大数据分析的基本条件,本次实验使用的气温数据需要利用Java API插入到数据库中。

3.1 idea项目初始化

创建一个maven项目,idea项目结构如下:

3.2 向pom.xml文件中导入依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>org.example</groupId>
  7. <artifactId>mongodbDemo</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <build>
  10. <plugins>
  11. <plugin>
  12. <groupId>org.apache.maven.plugins</groupId>
  13. <artifactId>maven-compiler-plugin</artifactId>
  14. <configuration>
  15. <source>7</source>
  16. <target>7</target>
  17. </configuration>
  18. </plugin>
  19. </plugins>
  20. </build>
  21. <dependencies>
  22. <!--单元测试依赖-->
  23. <dependency>
  24. <groupId>junit</groupId>
  25. <artifactId>junit</artifactId>
  26. <version>4.12</version>
  27. </dependency>
  28. <!--java操作mongoDB的驱动依赖-->
  29. <dependency>
  30. <groupId>org.mongodb</groupId>
  31. <artifactId>mongo-java-driver</artifactId>
  32. <version>3.12.1</version>
  33. </dependency>
  34. <dependency>
  35. <groupId>com.googlecode.json-simple</groupId>
  36. <artifactId>json-simple</artifactId>
  37. <version>1.1.1</version>
  38. </dependency>
  39. </dependencies>
  40. </project>

3.3 创建MongoDBUtil工具类

其中封装了MongoDB工具类通过连接池获取对象访问服务器的方法。

  1. package com.sjy.util;
  2. import com.mongodb.MongoClient;
  3. import com.mongodb.MongoClientOptions;
  4. import com.mongodb.ServerAddress;
  5. /**
  6. * 封装MongoDB工具类通过连接池获取对象访问服务器
  7. */
  8. public class MongoDBUtil {
  9. private static MongoClient mongoClient = null;
  10. private static MongoClientOptions.Builder builder = null;
  11. private static MongoClientOptions options = null;
  12. //服务器IP
  13. private static String HOST = "192.168.10.102";
  14. //端口
  15. private static int PORT = 27017;
  16. //用户名
  17. private static String USER = "root";
  18. //密码
  19. private static String PASSWORD = "111111";
  20. //与目标数据库可以建立的最大链接数
  21. private static int CONNECTIONS_PERHOST = 100;
  22. //这个参数是跟connectionPerHost配套的,当连接超过connectionPerHost的时候,需要建立新的连接
  23. //连接请求会被阻塞,这个参数就代表允许阻塞请求的最大值,超过这个值之后的请求都会报错
  24. private static int THREADS_ALLOWED_TO_BLOCK_FOR_CONNECTION_MULTIPLIER = 100;
  25. //与数据库建立链接的超过时间
  26. private static int CONNECT_TIMEOUT = 1000 * 60 * 20;
  27. //一个线程成功获取到一个可用数据库之前的最大等待时间
  28. private static int MAX_WAILTIME = 100 * 60 * 5;
  29. //执行IO操作的超过时间,默认为0,代表不超时
  30. private static int SOCKE_TIMEOUT = 0;
  31. /**
  32. * 初始化连接池
  33. */
  34. static {
  35. try {
  36. builder = new MongoClientOptions.Builder();
  37. // builder.set
  38. builder.connectionsPerHost(CONNECTIONS_PERHOST);
  39. builder.threadsAllowedToBlockForConnectionMultiplier(THREADS_ALLOWED_TO_BLOCK_FOR_CONNECTION_MULTIPLIER);
  40. builder.connectTimeout(CONNECT_TIMEOUT);
  41. builder.maxWaitTime(MAX_WAILTIME);
  42. builder.socketTimeout(SOCKE_TIMEOUT);
  43. options = builder.build();
  44. } catch (Exception e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. /**
  49. * 通过连接池获取连接对象并操作服务器
  50. */
  51. public static MongoClient getMongoClient() {
  52. if (mongoClient != null) {
  53. return mongoClient;
  54. }
  55. try {
  56. mongoClient = new MongoClient(new ServerAddress(HOST, PORT), options);
  57. return mongoClient;
  58. } catch (Exception e) {
  59. e.printStackTrace();
  60. return null;
  61. }
  62. }
  63. /**
  64. * 释放资源
  65. */
  66. public static void close(MongoClient mongoClient) {
  67. if (mongoClient != null) {
  68. mongoClient.close();
  69. }
  70. }
  71. }

3.4 Java API操作MongoDB

首先创建一个MongoClient实例来连接到本地运行在默认端口上的MongoDB服务器。接着,我们获取目标数据库和集合的引用。

接下来,创建一个新的Document对象,并将JSONObject中的所有键值对添加到这个Document对象中。最后,将这个Document对象插入到MongoDB集合中。这里的json文件就是上述爬虫程序爬取到的数据文件。

  1. package com.sjy.mongodb;
  2. import com.mongodb.MongoClient;
  3. import com.mongodb.client.FindIterable;
  4. import com.mongodb.client.MongoCollection;
  5. import com.mongodb.client.MongoDatabase;
  6. import com.sjy.util.MongoDBUtil;
  7. import org.bson.Document;
  8. import org.json.simple.JSONArray;
  9. import org.json.simple.JSONObject;
  10. import org.json.simple.parser.JSONParser;
  11. import org.json.simple.parser.ParseException;
  12. import java.io.FileReader;
  13. import java.io.IOException;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. import java.util.UUID;
  17. public class WeatherTest {
  18. public static void main(String[] args) {
  19. // 连接到MongoDB服务器
  20. MongoClient mongoClient = MongoDBUtil.getMongoClient();
  21. // 获取数据库和集合实例
  22. MongoDatabase database = mongoClient.getDatabase("my_database");
  23. MongoCollection<Document> collection = database.getCollection("weather");
  24. // 从JSON文件中读取数据
  25. List<Document> documents = new ArrayList<>();
  26. JSONParser parser = new JSONParser();
  27. try (FileReader reader = new FileReader("d:/data.json")) {
  28. Object obj = parser.parse(reader);
  29. JSONArray jsonArray = (JSONArray) obj;
  30. for (Object o : jsonArray) {
  31. JSONObject jsonObject = (JSONObject) o;
  32. String id = UUID.randomUUID().toString();
  33. Document document = new Document("_id", id)
  34. .append("data_time", jsonObject.get("data_time"))
  35. .append("high", jsonObject.get("high"))
  36. .append("low", jsonObject.get("low"))
  37. .append("weather", jsonObject.get("weather"));
  38. documents.add(document);
  39. }
  40. } catch (IOException | ParseException e) {
  41. System.err.println("Error reading data from file: " + e.getMessage());
  42. }
  43. // 执行批量插入
  44. collection.insertMany(documents);
  45. FindIterable<Document> weatherDo = collection.find();
  46. for (Document document : weatherDo) {
  47. System.out.println(document.toJson());
  48. }
  49. // 关闭MongoClient连接
  50. mongoClient.close();
  51. }
  52. }

最后测试数据是否插入成功

四、项目可视化

为了更好地理解和解释分析结果,我们使用Echarts创建了一系列图表,包括柱状图、饼图。这些可视化工具使我们能够直观地看到数据的模式和趋势。

flask项目结构如下:

4.1 可视化后端实现

本次项目可视化我使用了Python的flask框架作为后端。Flask是一个微框架,它比其他如Django等大型框架更简洁、轻巧。这意味着我可以快速搭建一个小型应用,并且在不引入过多额外依赖的情况下专注于核心功能——数据可视化。Flask默认集成了Jinja2模板引擎,它可以方便地将数据插入到HTML页面中,这对于动态生成包含可视化的网页非常有用。

引入项目所需库,连接MongoDB数据库,执行find()方法,获取所需要的数据,并将需要的数据添加到列表中发送给前端。本次实验需要的数据是日期、该日最高温度和最低温度。

  1. from flask import Flask, render_template, request
  2. # render_template作用是把html网页渲染完然后扔给服务器
  3. import pymongo
  4. import json
  5. # 创建一个app
  6. app = Flask(__name__)
  7. # 连接到MongoDB数据库
  8. client = pymongo.MongoClient("mongodb://192.168.10.102:27017/")
  9. # 选择数据库
  10. db = client["my_database"]
  11. # 选择集合
  12. collection = db["weather"]
  13. # 创建游标对象
  14. cursor = collection.find()
  15. data_time = []
  16. high = []
  17. low = []
  18. weather = {}
  19. for document in cursor:
  20. print(document)
  21. data_time.append(document.get('data_time')[5:])
  22. high.append(document.get('high'))
  23. low.append(document.get('low'))
  24. data = {
  25. 'data_time': data_time,
  26. 'high': high,
  27. 'low': low
  28. }
  29. @app.route("/")
  30. def show():
  31. return render_template("show.html", data=data)
  32. # 运行这个app
  33. if __name__ == '__main__':
  34. app.run()

4.2 可视化前端实现

本次项目可视化我使用ECharts 库,在前端代码中引入ECharts标签<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.4.3/echarts.common.min.js"></script> ECharts 是一个由百度商业前端数据可视化团队开发的开源数据可视化库。它基于 JavaScript,能够创建丰富的图表和图形,包括折线图、柱状图、饼图、地图等,用于展示和分析数据。并且ECharts 有一个清晰的 API 和详细的文档,开发者可以快速上手并创建出复杂的图表。

html代码,使用了echarts示例中的折线图,可以更清晰的展现某市上一个月的气温变化。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <!--引入echarts-->
  7. <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.4.3/echarts.common.min.js"></script>
  8. </head>
  9. <body>
  10. <div id="weather" style="width: 1000px; height: 700px;"></div>
  11. <script>
  12. // 获取从后端传递的数据
  13. var weather = echarts.init(document.getElementById("weather"))
  14. var option = {
  15. title: {
  16. text: '黄石市2023年11月气温变化'
  17. },
  18. tooltip: {
  19. trigger: 'axis'
  20. },
  21. legend: {},
  22. toolbox: {
  23. show: true,
  24. feature: {
  25. dataZoom: {
  26. yAxisIndex: 'none'
  27. },
  28. dataView: { readOnly: false },
  29. magicType: { type: ['line', 'bar'] },
  30. restore: {},
  31. saveAsImage: {}
  32. }
  33. },
  34. xAxis: {
  35. type: 'category',
  36. boundaryGap: false,
  37. data: {{data.data_time|tojson}}
  38. },
  39. yAxis: {
  40. type: 'value',
  41. axisLabel: {
  42. formatter: '{value} °C'
  43. }
  44. },
  45. series: [
  46. {
  47. name: 'Highest',
  48. type: 'line',
  49. data: {{data.high|tojson}},
  50. markPoint: {
  51. data: [
  52. { type: 'max', name: 'Max' },
  53. { type: 'min', name: 'Min' }
  54. ]
  55. },
  56. markLine: {
  57. data: [{ type: 'average', name: 'Avg' }]
  58. }
  59. },
  60. {
  61. name: 'Lowest',
  62. type: 'line',
  63. data: {{data.low|tojson}},
  64. // markPoint: {
  65. // data: [{ name: '周最低', value: -2, xAxis: 1, yAxis: -1.5 }]
  66. // },
  67. markLine: {
  68. data: [
  69. { type: 'average', name: 'Avg' },
  70. [
  71. {
  72. symbol: 'none',
  73. x: '90%',
  74. yAxis: 'max'
  75. },
  76. {
  77. symbol: 'circle',
  78. label: {
  79. position: 'start',
  80. formatter: 'Max'
  81. },
  82. type: 'max',
  83. name: '最高点'
  84. }
  85. ]
  86. ]
  87. }
  88. }
  89. ]
  90. };
  91. //把配置单给echarts
  92. weather.setOption(option)
  93. </script>
  94. </body>
  95. </html>

4.3 可视化效果图

总结

本实验的主要目标是使用MongoDB数据库存储黄石市上一个月的气温数据,并通过可视化的手段展示结果。我们首先使用Python爬虫从天气网站上抓取了一年内的所有气温数据。然后,将数据转存为json格式,确保后续使用Java API存储到MongoDB数据库中数据文件的解析性。最后使用flask框架连接MongoDB数据库,查询出存储的所有气温数据,再过滤出我们需要的数据。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/814093
推荐阅读
相关标签
  

闽ICP备14008679号