zoukankan      html  css  js  c++  java
  • 课堂练习-移动端疫情展示

    题目要求:

    要求开发一款移动端的全世界疫情实时查询系统。

    要求将前两周的项目合并为一个完整的项目。

    采用统一的数据库。(建议MySQL数据库)

    实现从数据采集、数据存储、数据查询(WEB端和移动端)一体全世界实时疫情查询系统。

    以本机数据库为服务器端,web端和移动端连接远程数据库实现数据共享,要求数据库表格式统一化。

    查询显示当前最新时间的数据,可以查询任一时间任一地点的数据。该系统要求在服务器端发布,可以通过IP地址访问。

    设计思想:

    数据爬取:借助python爬虫语句,将疫情数据爬取存储到MySQL;

     web端:结合前两周的项目,添加世界范围的疫情数据,以及简单的查询功能;

     移动端:Android开发,连接MySQL数据库,实现简单的查询功能;

    python代码:

    import json
    
    import numpy as np
    import pymysql
    import requests
    from bs4 import BeautifulSoup
    import datetime
    
    url = 'https://ncov.dxy.cn/ncovh5/view/pneumonia?from=timeline&isappinstalled=0'  #请求地址
    headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'}#创建头部信息
    response =  requests.get(url,headers = headers)  #发送网络请求
    #print(response.content.decode('utf-8'))#以字节流形式打印网页源码
    content = response.content.decode('utf-8')
    #print(content)
    soup = BeautifulSoup(content, 'html.parser')
    listA = soup.find_all(name='script',attrs={"id":"getAreaStat"})
    #世界确诊getAreaStat
    listB = soup.find_all(name='script',attrs={"id":"getListByCountryTypeService2true"})
    #listA = soup.find_all(name='div',attrs={"class":"c-touchable-feedback c-touchable-feedback-no-default"})
    account = str(listA)
    world_messages = str(listB)[95:-21]
    messages = account[52:-21]
    messages_json = json.loads(messages)
    print(world_messages)
    world_messages_json = json.loads(world_messages)
    valuesList = []
    cityList = []
    worldList = []
    now_time = datetime.datetime.now().strftime('%Y-%m-%d')
    
    for k in range(len(world_messages_json)):
        worldvalue = (now_time,
                 world_messages_json[k].get('countryType'),world_messages_json[k].get('continents'),world_messages_json[k].get('provinceId'),world_messages_json[k].get('provinceName'),
                 world_messages_json[k].get('provinceShortName'),world_messages_json[k].get('cityName'),world_messages_json[k].get('currentConfirmedCount'),world_messages_json[k].get('confirmedCount'),
                 world_messages_json[k].get('suspectedCount'),world_messages_json[k].get('curedCount'),world_messages_json[k].get('deadCount'),world_messages_json[k].get('locationId'),
                 world_messages_json[k].get('countryShortCode'),)
        worldList.append(worldvalue)
    for i in range(len(messages_json)):
        #value = messages_json[i]
        value = (now_time,messages_json[i].get('provinceName'),messages_json[i].get('provinceShortName'),messages_json[i].get('currentConfirmedCount'),messages_json[i].get('confirmedCount'),messages_json[i].get('suspectedCount'),messages_json[i].get('curedCount'),messages_json[i].get('deadCount'),messages_json[i].get('comment'),messages_json[i].get('locationId'),messages_json[i].get('statisticsData'))
        valuesList.append(value)
        cityValue = messages_json[i].get('cities')
        #print(cityValue)
        for j in range(len(cityValue)):
            cityValueList = (cityValue[j].get('cityName'),cityValue[j].get('currentConfirmedCount'),cityValue[j].get('confirmedCount'),cityValue[j].get('suspectedCount'),cityValue[j].get('curedCount'),cityValue[j].get('deadCount'),cityValue[j].get('locationId'),messages_json[i].get('provinceShortName'))
            #print(cityValueList)
            cityList.append(cityValueList)
        #cityList.append(cityValue)
    db = pymysql.connect("localhost", "root", "123456", "mytest", charset='utf8')
    cursor = db.cursor()
    array = np.asarray(valuesList[0])
    #sql_clean_world = "TRUNCATE TABLE world_map"
    sql_clean_city = "TRUNCATE TABLE city_map"
    sql_clean_json = "TRUNCATE TABLE province_data_from_json"
    sql_clean_province = "TRUNCATE TABLE province_map"
    sql_clean_world = "TRUNCATE TABLE world_map"
    sql1 = "INSERT INTO city_map values (%s,%s,%s,%s,%s,%s,%s,%s)"
    sql_world = "INSERT INTO world_map values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
    #sql = "INSERT INTO province_map values (0,'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s') "
    sql = "INSERT INTO province_map values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) "
    #sql = "INSERT INTO province_map (provinceName,provinceShortName,correntConfirmedCount,confirmedCount,suspectedCount,curedCount,deadCount,comment,locationId,statisticsData) values (0,'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s') "
    #sql = """INSERT INTO province_map (provinceName,provinceShortName,correntConfirmedCount,confirmedCount,suspectedCount,curedCount,deadCount,comment,locationId,statisticsData) values ('湖北省', '湖北', 43334, 64786, 0, 18889, 2563, '', 420000, 'https://file1.dxycdn.com/2020/0223/618/3398299751673487511-135.json')"""
    value_tuple = tuple(valuesList)
    cityTuple = tuple(cityList)
    worldTuple = tuple(worldList)
    print(worldTuple)
    print(tuple(value_tuple))
    try:
        #cursor.execute(sql_clean_city)
        #cursor.execute(sql_clean_province)
        #cursor.executemany(sql, value_tuple)
        #cursor.executemany(sql1,cityTuple)
        db.commit()
    except:
        print('执行失败,进入回调1')
        db.rollback()
    
    try:
        #cursor.execute(sql_clean_city)
        #cursor.execute(sql_clean_province)
        #cursor.execute(sql_clean_world)
        #cursor.executemany(sql, value_tuple)
        #cursor.executemany(sql1,cityTuple)
        cursor.executemany(sql_world, worldTuple)
        db.commit()
    except:
        print('执行失败,进入回调2')
        db.rollback()
    try:
        #cursor.execute(sql_clean_city)
        #cursor.execute(sql_clean_province)
        cursor.executemany(sql, value_tuple)
        #cursor.executemany(sql1,cityTuple)
        db.commit()
    except:
        print('执行失败,进入回调3')
        db.rollback()
    
    try:
        #cursor.execute(sql_clean_city)
        #cursor.execute(sql_clean_province)
        #cursor.executemany(sql, value_tuple)
        #cursor.executemany(sql1,cityTuple)
        db.commit()
    except:
        print('执行失败,进入回调4')
        db.rollback()
    #print(messages_json)
    #print(account[52:-21])
    # soupDiv = BeautifulSoup(listA,'html.parser')
    # listB = soupDiv.find_all(name='div',attrs={"class":"c-gap-bottom-zero c-line-clamp2"})
    #for i in listA:
        #print(i)
    #listA[12]
    #print(listA)
    
    
    db.close()

    android代码:

    package com.example.myapplication;
    import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * 数据库工具类:连接数据库用、获取数据库数据用 * 相关操作数据库的方法均可写在该类 */ public class DBUtils { private static String driver = "com.mysql.jdbc.Driver";// MySql驱动 private static String user = "root";// 用户名 private static String password = "123456";// 密码 private static Connection getConn(String dbName) { Connection connection = null; try { Class.forName(driver);// 动态加载类 String ip = "192.168.0.101";// 写成本机地址,不能写成localhost,同时手机和电脑连接的网络必须是同一个 // 尝试建立到给定数据库URL的连接 connection = DriverManager.getConnection("jdbc:mysql://" + ip + ":3306/" + dbName, user, password); } catch (Exception e) { e.printStackTrace(); } return connection; } public static List
    <information> search(String condition, String country_name){ List<information> list = new ArrayList<>(); Connection connection = getConn("mytest"); String sql = ""; //System.out.println(condition); //选择条件 if(condition.equals("国家")){ //模糊查询 sql = "select * from world_map where provinceName like ?"; } if(condition.equals("时间")){ sql = "select * from world_map where date like ?"; } System.out.println(country_name); if(connection !=null){ try { PreparedStatement ps = connection.prepareStatement(sql); if(ps!=null){ ps.setString(1,"%"+country_name+"%"); ResultSet rs = ps.executeQuery(); if(rs!=null){ while(rs.next()){ information worldData = new information(); worldData.setCountryname(rs.getString("provinceName")); worldData.setConfirmed(rs.getString("confirmedCount")); worldData.setSuspected(rs.getString("suspectedCount")); worldData.setDead(rs.getString("deadCount")); worldData.setHealed(rs.getString("curedCount")); worldData.setLastUpdateTime(rs.getString("date")); list.add(worldData); } connection.close(); ps.close(); return list; }else{ return null; } }else{ return null; } } catch (SQLException e) { e.printStackTrace(); return null; } }else{ return null; } } }
    package com.example.myapplication;
    public class information { private int id; private String countryname; private String confirmed; private String suspected; private String dead; private String healed; private String lastUpdateTime;
    public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCountryname() { return countryname; } public void setCountryname(String countryname) { this.countryname = countryname; } public String getConfirmed() { return confirmed; } public void setConfirmed(String confirmed) { this.confirmed = confirmed; } public String getSuspected() { return suspected; } public void setSuspected(String suspected) { this.suspected = suspected; } public String getDead() { return dead; } public void setDead(String dead) { this.dead = dead; } public String getHealed() { return healed; } public void setHealed(String healed) { this.healed = healed; } public String getLastUpdateTime() { return lastUpdateTime; } public void setLastUpdateTime(String lastUpdateTime) { this.lastUpdateTime = lastUpdateTime; } }
    package com.example.myapplication;
    
    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.RadioButton;
    import android.widget.RadioGroup;
    import android.widget.TextView;
    import java.util.List;
    
    @SuppressLint("Registered")
    public class MainActivity extends Activity {
        private EditText et_name;
        private Button btn_get_data;
        private TextView tv_data;
        private RadioGroup rg_check;
        private RadioButton rb_date;
        private RadioButton rb_country;
        private String condition;
        @SuppressLint("HandlerLeak")
        private Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what){
                    case 0x11:
                        String s = (String) msg.obj;
                        tv_data.setText(s);
                        break;
                    case 0x12:
                        String ss = (String) msg.obj;
                        tv_data.setText(ss);
                        break;
                }
            }
        };
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // 控件的初始化
            btn_get_data = findViewById(R.id.btn_get_data);
            tv_data = findViewById(R.id.tv_data);
            et_name = findViewById(R.id.et_name);
            rb_date = findViewById(R.id.rb_date);
            rb_country = findViewById(R.id.rb_country);
            rg_check = findViewById(R.id.rg_select);
            rg_check.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                public void onCheckedChanged(RadioGroup group, int checkedId) {
                    //如果‘时间’这个单选按钮被选中了
                    if(rb_date.getId()==checkedId){
                        //弹出吐司通知
                        //Toast.makeText(MainActivity.this, rb_date.getText().toString(), Toast.LENGTH_LONG).show();
                        //获取选中按钮对应的文本信息
                        condition = rb_date.getText().toString().trim();
                    }else if(rb_country.getId()==checkedId){
                        //Toast.makeText(MainActivity.this, rb_country.getText().toString(), Toast.LENGTH_LONG).show();
                        condition = rb_country.getText().toString().trim();
                    }
                }
            });
            //如果没有选择默认按时间查询
            if (condition == null){
                condition = rb_date.getText().toString().trim();
            }
            setListener();
        }
        /**
         * 设置监听
         */
        private void setListener() {
            // 按钮点击事件
            btn_get_data.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 创建一个线程来连接数据库并获取数据库中对应表的数据
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            String name = et_name.getText().toString().trim();
                            //调用数据库帮助类中的方法取数据
                            List<information> list = DBUtils.search(condition,name);
                            Message message = handler.obtainMessage();
                            if (list != null) {
                                String s = "";
                                for (int i = 0; i < list.size(); i++) {
                                    s += "国家:" + list.get(i).getCountryname() + "
    ";
                                    s += "最新更新时间:" + list.get(i).getLastUpdateTime() + "
    ";
                                    s += "确诊人数为:  " + list.get(i).getConfirmed() + "
    ";
                                    s += "治愈人数为:  " + list.get(i).getHealed() + "
    ";
                                    s += "死亡人数为:  " + list.get(i).getDead() + "
    " + "
    ";
                                }
                                //0x11、0x12消息的定位标志
                                message.what = 0x12;
                                message.obj = s;
                            } else {
                                message.what = 0x11;
                                message.obj = "查询结果为空";
                            }
                            handler.sendMessage(message);
                            // 发消息通知主线程更新UI
                        }
                    }).start();
                }
            });
        }
    }
    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        android:padding="15dp">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <RadioGroup
                android:id="@+id/rg_select"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:paddingLeft="20dp"
                android:layout_marginTop="20dp">
                <RadioButton
                    android:id="@+id/rb_date"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="时间"
                    android:textSize="20sp"
                    android:checked="true"/>
                <RadioButton
                    android:id="@+id/rb_country"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="国家"
                    android:textSize="20sp"/>
            </RadioGroup>
            <EditText
                android:id="@+id/et_name"
                android:padding="10dp"
                android:textSize="16sp"
                android:gravity="center"
                android:hint="输入要查询的内容"
                android:layout_below="@id/rg_select"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
            <Button
                android:id="@+id/btn_get_data"
                android:layout_margin="15dp"
                android:textSize="16sp"
                android:text="查询"
                android:layout_below="@id/et_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
            <TextView
                android:id="@+id/tv_data"
                android:padding="10dp"
                android:textSize="16sp"
                android:gravity="center"
                android:text="内容"
                android:layout_below="@+id/btn_get_data"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </RelativeLayout>
    </ScrollView>

    运行截图:


    所遇到的问题:

    Android无法连接到数据库 :Communications link failure

     解决方法:将ip地址改为本机ip地址。若仍出现此错误,将jdbc 的jar包更换为低版本。

    时间记录日志:

    阶段 预估时间 实耗时间 出现问题 解决方案
    爬取数据 60min 125min 获取数据无法转换为json格式 打印输出爬取数据,删除多余字符
    编写web查询 45min 75min    
    绘制世界地图 80min 150min 找不到world.js资源;地图无法显示 借助网络查询
    Android连接MySQL 20min 70min 连接数据库失败 将jdbc-connector-java.jar驱动换为低版本
    编写Android查询

    90min

    160min    
  • 相关阅读:
    unity ab包打包和加载的简单学习示例
    项目整理回顾1,关于单例使用
    关于lua闭包导致引用无法释放内存泄露
    unity lua require dofile loadfile 区别
    unity editor模式下读取文件夹资源
    unity texture 占用内存大小对比
    关于unity贴图压缩
    内聚,耦合,解耦和,依赖倒置
    lua type 获取 类型
    Unity+NGUI多分辨率适配方案
  • 原文地址:https://www.cnblogs.com/zql-42/p/13027640.html
Copyright © 2011-2022 走看看