一、要求
1、要求开发一款移动端的全世界疫情实时查询系统。
2、要求将前两周的项目合并为一个完整的项目。 采用统一的数据库。(建议MySQL数据库)
3、实现从数据采集、数据存储、数据查询(WEB端和移动端)一体全世界实时疫情查询系统。
4、以本机数据库为服务器端,web端和移动端连接远程数据库实现数据共享,要求数据库表格式统一化。
5、查询显示当前最新时间的数据,可以查询任一时间任一地点的数据。该系统要求在服务器端发布,可以通过IP地址访问。
二、设计思路
1、数据准备,使用python从网上爬取疫情各地的数据,并存入mysql数据库
2、数据展示,遇到了很大的难题:(Android获取数据时,连不上数据库)按照老师要求我的解决方法是从Android发送http请求到web端web端在从数据库获取数据,以此来做到web端和我Android端公用一套数据。
3、使用volley的stringrequest向web请求数据(json)
4、使用Gson进行数据转换。
5、使用MPAndroidChart的柱状图来进行数据可视化
三、psp表
日期 | 开始时间 | 结束时间 | 中断时间 | 净时间 | 活动 | 备注 |
2020-3-17 | 15:18 | 15:36 | 3分钟 | 22分钟 |
更新上周所爬取的内容并爬取其他各国的数据 |
比较容易 |
15:37 | 19:46 | 10分钟 | 239 | 尝试在Android中直接连接mysql数据库 | 失败,被迫放弃! | |
19:47 | 21:35 | 108分钟 |
学习okhttp的发送网络请求的方法 https://www.jianshu.com/p/5bc65d66a4b2 学习volley的发送网络请求的方法 https://www.cnblogs.com/lizhanqi/p/5712581.html |
1、okhttp实现向自己的电脑发送请求失败 2、volley的stringrequest实现向自己的电脑发送请求成功 |
||
21:36 | 22:56 | 20分钟 | 60分钟 | 实现web端的查询和对应的Android 的请求的响应 |
因为8G内存承受不了web+Android+模拟器一起运行, 调试很麻烦。哎! |
|
23:15 | 23:40 | 5分钟 | 20分钟 | 实现Android的UI界面 | 基础知识忘得差不多了! | |
2020-03-18 | 0:05 | 1:00 | 10分钟 | 45分钟 | 完成控件绑定,发送请求、事件监听等逻辑代码 | 自己写的很少,很多样板代码和复制粘贴。。。 |
1:05 | 2:10 | 5分钟 | 60分钟 | 调试改错 |
有关发送网络请求的程序,请求失败不要急着改代码, 因为有可能是网络不好、、、(我就是) |
|
9:50 | 13:17 | 30分钟 | 177分钟 |
学习 MPAndroidChart图表 https://www.jianshu.com/p/76de8cea75ae 实现数据可视化展示 |
新知识不好学啊!!! |
四、遇到的问题
1、Android获取数据时,连不上数据库(未解决)
导包无误:
编译可以通过,驱动是 Class.forName("com.mysql.cj.jdbc.Driver");就是连不上。
针对这个问题研究了3个多小时,最后我放弃了!哎!
2、MPAndroidChart可视化 x 轴 显示是字符串及地区名(默认是float)
解决方法:
第一步:重新 ValueFormatter 类
package com.me.http; import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.formatter.ValueFormatter; import java.text.DecimalFormat; public class MyValueFormatter extends ValueFormatter{ private final DecimalFormat mFormat; private String suffix; private String [] str; public MyValueFormatter(String suffix,String [] str) { mFormat = new DecimalFormat("0000"); this.suffix = suffix; this.str = str; } @Override public String getFormattedValue(float value) { return mFormat.format(value) + suffix; } @Override public String getAxisLabel(float value, AxisBase axis) { if (axis instanceof XAxis) { return str[(int)value]; } else if (value > 0) { return mFormat.format(value) + suffix; } else { return mFormat.format(value); } } }
第二步:准备String数组(地区名数组)
viewModel = ViewModelProviders.of(requireActivity()).get(ViewModel.class); list = viewModel.getList(); for (int i = 0; i < 7; i++) { str[i] = list.get(i).getName(); }
第三步:准备实体时将与前准备的String数组下标和与之对应的数据存入
ArrayList<BarEntry> values = new ArrayList<>(); for (int i = 0; i < 7; i++) { BarEntry barEntry = new BarEntry(i,Float.valueOf(list.get(i).getConfirm())); values.add(barEntry); }
第四部:使用自己的ValueFormatter 设置 x 轴所显示的数据
ValueFormatter custom = new MyValueFormatter(" 1",str); xAxis.setValueFormatter(custom);
五、源代码
1、python爬取中国各省市数据
import requests import json from pymysql import * import requests from retrying import retry headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36" ,"Referer": "https://wp.m.163.com/163/page/news/virus_report/index.html?_nw_=1&_anw_=1"} def _parse_url(url): response = requests.get(url,headers=headers,timeout=3) #3秒之后返回 return response.content.decode() def parse_url(url): try: html_str = _parse_url(url) except: html_str = None return html_str class yiqing: f = 0 url="https://c.m.163.com/ug/api/wuhan/app/data/list-total?t=316765429316" def getContent_list(self,html_str): dict_data = json.loads(html_str) #各省的数据 content_list = dict_data["data"] return content_list def saveContent_list(self,i): # 打开数据库连接(ip/数据库用户名/登录密码/数据库名) con = connect("localhost", "root", "root", "text") # 使用 cursor() 方法创建一个游标对象 cursor cursors = con.cursor() # 使用 execute() 方法执行 SQL 查询 返回的是你影响的行数 if self.f ==0 : cursors.execute("delete from citys") cursors.execute("delete from provinces") self.f = self.f+1 row = cursors.execute("insert into provinces values(%s,%s,%s,%s,%s,%s,%s,%s)", (i.get('id'),i.get('name'),i.get('total').get('confirm'), i.get('total').get('suspect'),i.get('total').get('heal'), i.get('total').get('dead'),i.get('total').get('severe'), i.get('lastUpdateTime'))) province = i.get('name') for j in i.get('children'): row = cursors.execute("insert into citys (id,name,confirm,suspect,heal,dead,severe,lastUpdateTime,province) values(%s,%s,%s,%s,%s,%s,%s,%s,%s)", (j.get('id'),j.get('name'),j.get('total').get('confirm'), j.get('total').get('suspect'),j.get('total').get('heal'), j.get('total').get('dead'),j.get('total').get('severe'), j.get('lastUpdateTime'),province)) con.commit()#提交事务 con.close()# 关闭数据库连接 def run(self): #实现主要逻辑 #请求数据 html_str = parse_url(self.url) #获取数据 content_list = self.getContent_list(html_str) values = content_list["areaTree"][0]["children"] for i in values: self.saveContent_list(i) if __name__ == '__main__': yq = yiqing() yq.run() print('爬取,存储成功!!')
2、python爬取其他各国数据
import requests import json from pymysql import * import requests from retrying import retry headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36" ,"Referer": "https://wp.m.163.com/163/page/news/virus_report/index.html?_nw_=1&_anw_=1"} def _parse_url(url): response = requests.get(url,headers=headers,timeout=3) #3秒之后返回 return response.content.decode() def parse_url(url): try: html_str = _parse_url(url) except: html_str = None return html_str class yiqing: f = 0 url="https://c.m.163.com/ug/api/wuhan/app/data/list-total?t=316765429316" def getContent_list(self,html_str): dict_data = json.loads(html_str) #各省的数据 content_list = dict_data["data"] return content_list def saveContent_list(self,i): # 打开数据库连接(ip/数据库用户名/登录密码/数据库名) con = connect("localhost", "root", "root", "text") # 使用 cursor() 方法创建一个游标对象 cursor cursors = con.cursor() # 使用 execute() 方法执行 SQL 查询 返回的是你影响的行数 if self.f ==0 : cursors.execute("delete from world") self.f = self.f+1 row = cursors.execute("insert into world values(%s,%s,%s,%s,%s,%s,%s,%s)", (i.get('id'),i.get('name'),i.get('total').get('confirm'), i.get('total').get('suspect'),i.get('total').get('heal'), i.get('total').get('dead'),i.get('total').get('severe'), i.get('lastUpdateTime'))) con.commit()#提交事务 con.close()# 关闭数据库连接 def run(self): #实现主要逻辑 #请求数据 html_str = parse_url(self.url) #获取数据 content_list = self.getContent_list(html_str) values = content_list["areaTree"] for i in values: self.saveContent_list(i) if __name__ == '__main__': yq = yiqing() yq.run() print('爬取,存储成功!!')
3、Android工程的github地址:https://github.com/xiaotian12-call/yiqing_app
六、运行测试