【项目】python爬取千锋教育数据并大屏可视化

基于python实现的“千锋教育数据可视化大屏”

一、开发环境

开发工具

  • IntelliJ IDEA 2023.2.1
  • Visual Studio Code
  • MongoDB Compass
  • Google Chrome

开发环境 (技术)

  • python 3.11.4
  • MongoDB 7.0.1
  • HTML
  • JS
  • CSS

所用到主要的python库

  • requests
  • pymongo
  • pandas
  • pyecharts

二、整体效果

在这里插入图片描述

三、目录详情

在这里插入图片描述

四、启动教程

  1. 安装依赖库

    • pymongo

      pip install pymongo
      
    • pandas

      pip install pandas
      
    • pyecharts

      pip install pyecharts
      
  2. 启动“启动程序.py”

    在这里插入图片描述

    控制台出现以下界面,说明启动成功!

在这里插入图片描述

五、爬取到的数据(MongoDB数据库)

  • 数据集

    在这里插入图片描述

  • 学生数据

    在这里插入图片描述

六、代码部分

  • config.py

    # 数据库服务器
    MONGO_URL = 'localhost'
    # 数据库
    MONGO_DB = 'qianfeng'
    # 数据库表
    MONGO_TABLE = 'student'
    
  • 千锋教育数据爬虫.py

    import json
    import random
    import pymongo
    import requests
    import logging as log
    
    from src.前锋教育可视化.config import *
    
    
    
    '''' 【第一部分】用于初始化对象 '''
    # 请求url
    BasicsUrl = 'http://www.qfedu.com/student/employment/'
    
    # 日志级别:DEBUG
    # 输出文件:default.log
    fm = "%(asctime)s [%(funcName)s:%(lineno)d] %(levelname)s [%(name)s] %(message)s"
    log.basicConfig(level=log.DEBUG,format=fm,filename="default.log",encoding="UTF-8")
    # log.basicConfig(level=log.DEBUG, format=fm, encoding="UTF-8")
    log.debug("程序初始化中......")
    
    # 创建MongoDB连接对象
    client = pymongo.MongoClient(MONGO_URL)
    db = client[MONGO_DB]
    
    # 创建浏览器对象
    # browser = webdriver.Chrome()
    
    # 城市参照字典(为了避免多次去请求,已将响应数据写成字典)
    contrast = {'盐城市': '江苏', '宿州市': '安徽', '岳阳市': '湖南', '邵阳市': '湖南', '乌兰察布市': '内蒙古自治区',
                '新乡市': '河南', '呼伦贝尔市': '内蒙古自治区', '长沙市': '湖南', '广州市': '广东', '宁德市': '福建',
                '阳江市': '广东', '毕节地区': '贵州', '无锡市': '江苏', '东营市': '山东', '仙桃市': '湖北',
                '太原市': '山西', '濮阳市': '河南', '驻马店市': '河南', '丹东市': '辽宁', '许昌市': '河南',
                '庆阳市': '甘肃', '商洛市': '陕西', '惠州市': '广东', '朝阳市': '辽宁', '渭南市': '陕西',
                '莆田市': '福建', '淮南市': '安徽', '海口市': '海南', '巴中市': '四川', '台州市': '浙江',
                '辽阳市': '辽宁', '哈尔滨市': '黑龙江', '忻州市': '山西', '沈阳市': '辽宁', '泰安市': '山东',
                '南阳市': '河南', '龙岩市': '福建', '舟山市': '浙江', '保山市': '云南', '珠海市': '广东',
                '随州市': '湖北', '临沂市': '山东', '攀枝花市': '四川', '天门市': '湖北', '西安市': '陕西',
                '泰州市': '江苏', '阜新市': '辽宁', '达州市': '四川', '牡丹江市': '黑龙江',
                '锡林郭勒盟': '内蒙古自治区', '吕梁市': '山西', '湛江市': '广东', '南京市': '江苏', '资阳市': '四川',
                '济南市': '山东', '乌鲁木齐市': '新疆维吾尔自治区', '江门市': '广东', '凉山彝族自治州': '四川',
                '玉溪市': '云南', '通辽市': '内蒙古自治区', '广元市': '四川', '南通市': '江苏', '扬州市': '江苏',
                '漯河市': '河南', '潮州市': '广东', '东莞市': '广东', '池州市': '安徽', '酒泉市': '甘肃',
                '玉林市': '广西壮族自治区', '焦作市': '河南', '柳州市': '广西壮族自治区', '六盘水市': '贵州',
                '湘潭市': '湖南', '佳木斯市': '黑龙江', '克拉玛依市': '新疆维吾尔自治区', '淄博市': '山东',
                '常德市': '湖南', '西宁市': '青海', '北海市': '广西壮族自治区', '湘西土家族苗族自治州': '湖南',
                '蚌埠市': '安徽', '绥化市': '黑龙江', '天水市': '甘肃', '福州市': '福建', '十堰市': '湖北',
                '日照市': '山东', '佛山市': '广东', '沧州市': '河北', '天津': '天津', '连云港市': '江苏',
                '德阳市': '四川', '绍兴市': '浙江', '德州市': '山东', '云浮市': '广东', '承德市': '河北',
                '宜昌市': '湖北', '济宁市': '山东', '泉州市': '福建', '内江市': '四川', '银川市': '宁夏回族自治区',
                '上饶市': '江西', '松原市': '吉林', '唐山市': '河北', '重庆': '重庆', '固原市': '宁夏回族自治区',
                '芜湖市': '安徽', '保定市': '河北', '运城市': '山西', '宿迁市': '江苏', '绵阳市': '四川',
                '周口市': '河南', '徐州市': '江苏', '青岛市': '山东', '厦门市': '福建', '汉中市': '陕西',
                '邢台市': '河北', '三亚市': '海南', '河源市': '广东', '嘉兴市': '浙江', '潍坊市': '山东',
                '大庆市': '黑龙江', '济源市': '河南', '金华市': '浙江', '襄樊市': '湖北', '枣庄市': '山东',
                '桂林市': '广西壮族自治区', '张家界市': '湖南', '晋城市': '山西', '三门峡市': '河南', '萍乡市': '江西',
                '南充市': '四川', '平顶山市': '河南', '清远市': '广东', '南昌市': '江西', '泸州市': '四川',
                '郴州市': '湖南', '博尔塔拉蒙古自治州': '新疆维吾尔自治区', '湖州市': '浙江', '镇江市': '江苏',
                '贵阳市': '贵州', '包头市': '内蒙古自治区', '南宁市': '广西壮族自治区', '马鞍山市': '安徽',
                '武威市': '甘肃', '北京': '北京', '崇左市': '广西壮族自治区', '邯郸市': '河北',
                '梧州市': '广西壮族自治区', '荆州市': '湖北', '吴忠市': '宁夏回族自治区', '株洲市': '湖南',
                '晋中市': '山西', '亳州市': '安徽', '盘锦市': '辽宁', '长治市': '山西', '成都市': '四川',
                '石家庄市': '河北', '黄冈市': '湖北', '曲靖市': '云南', '孝感市': '湖北',
                '吐鲁番地区': '新疆维吾尔自治区', '榆林市': '陕西', '大理白族自治州': '云南', '温州市': '浙江',
                '上海': '上海', '大连市': '辽宁', '肇庆市': '广东', '金昌市': '甘肃', '景德镇市': '江西',
                '汕头市': '广东', '滁州市': '安徽', '黑河市': '黑龙江', '吉安市': '江西', '海南藏族自治州': '青海',
                '丽水市': '浙江', '锦州市': '辽宁', '临汾市': '山西', '廊坊市': '河北', '永州市': '湖南',
                '威海市': '山东', '杭州市': '浙江', '延安市': '陕西', '六安市': '安徽', '衡阳市': '湖南',
                '中山市': '广东', '阜阳市': '安徽', '宁波市': '浙江', '阿克苏地区': '新疆维吾尔自治区',
                '常州市': '江苏', '滨州市': '山东', '开封市': '河南', '信阳市': '河南', '赣州市': '江西',
                '遵义市': '贵州', '鄂尔多斯市': '内蒙古自治区', '长春市': '吉林', '鞍山市': '辽宁', '宣城市': '安徽',
                '秦皇岛市': '河北', '宜春市': '江西', '荆门市': '湖北', '鹤壁市': '河南', '商丘市': '河南',
                '眉山市': '四川', '苏州市': '江苏', '怀化市': '湖南', '自贡市': '四川', '呼和浩特市': '内蒙古自治区',
                '吉林市': '吉林', '洛阳市': '河南', '合肥市': '安徽', '拉萨市': '西藏自治区', '大同市': '山西',
                '衢州市': '浙江', '河池市': '广西壮族自治区', '衡水市': '河北', '咸宁市': '湖北', '昆明市': '云南',
                '咸阳市': '陕西', '宜宾市': '四川', '葫芦岛市': '辽宁', '黔南布依族苗族自治州': '贵州',
                '新余市': '江西', '赤峰市': '内蒙古自治区', '张家口市': '河北', '聊城市': '山东', '淮安市': '江苏',
                '营口市': '辽宁', '朔州市': '山西', '烟台市': '山东', '宝鸡市': '陕西', '淮北市': '安徽',
                '遂宁市': '四川', '武汉市': '湖北', '安阳市': '河南', '昭通市': '云南', '贵港市': '广西壮族自治区',
                '黄石市': '湖北', '九江市': '江西', '深圳市': '广东', '梅州市': '广东',
                '阿勒泰地区': '新疆维吾尔自治区', '兰州市': '甘肃', '安庆市': '安徽', '郑州市': '河南'}
    '''' 【第二部分】用于定义一些函数 '''
    
    
    # 请求的方法
    def httpGet(url):
        headers_list = [
            {
                'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (iPad; CPU OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666'
            }, {
                'user-agent': 'Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.188 Safari/537.36 CrKey/1.54.250320'
            }, {
                'user-agent': 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+'
            }, {
                'user-agent': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 6.0.1; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)'
            }, {
                'user-agent': 'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 11; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36'
            }, {
                'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1'
            }, {
                'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
            }, {
                'user-agent': 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1'
            },
        ]
        proxies = {
            'http': '127.0.0.1:1212',
            'https': '127.0.0.1:1212'
        }
        headers = random.choice(headers_list)
        return requests.get(url=url, headers=headers, timeout=20);
    
    
    # 请求接口,并将数据保存到MongoDB
    def insertDB(star, end):
        for i in range(star, end + 1):
            log.debug(f"已获取{i}年学生就业数据")
            data = httpGet(f'http://jx.1000phone.net/teacher.php/Api/studentJobData_year?date={i}')
            res = json.loads(data.text)
            # 构建info元组
            jobInfo = {
                "year": i,
                "topSalary": res['topSalary'],
                "avgSalary": res['avgSalary'],
                "goodSalaryRate": res['goodSalaryRate'],
                "jobCount": res['jobCount'],
                "jobRate": res['jobRate'],
            }
            # 将数据保存到MongoDB
            if db["jobInfo"].insert_one(jobInfo):
                log.debug(f"{i}年就业统计信息已保存到MongoDB")
            # 保存学生信息
            if db['student'].insert_many(res['student']):
                log.debug(f"{i}年学生信息已保存")
    
    
    # 爬取取视频信息
    def getVieoData():
        for i in range(1, 13):
            subjectData = httpGet(f"https://video.qfedu.com/library/api/subjectstage/list/{i}").text
            subjectList = json.loads(subjectData)["data"][0]["subjectStageCourseEntities"]
            dbName = json.loads(subjectData)["data"][0]["stageName"]
            if db[f"{dbName}"].insert_many(subjectList):
                log.debug(f"{dbName}课程已导入MongoDB")
    
    
    # 通过地址获取省份的函数
    def getGeocodes(city):
        contrast = {}
        for i in city:
            str = "市辖区省直辖县级行政单位省直辖行政单位"
            if (i in str):
                continue
            else:
                data = requests.get(
                    f"https://restapi.amap.com/v3/geocode/geo?address={i}&output=json&key=c6684350b2db997c28d33309e5589e58").text
                res = json.loads(data)
                if res["status"] != "0":
                    geocodes = res["geocodes"][0]["province"]
                    contrast[f"{i}"] = geocodes
        return contrast
    
    
    # 格式化地理信息
    def formatAddress():
        collection = db['student']
        # 定义聚合查询的管道
        pipeline = [
            {
                '$group': {
                    '_id': '$city',  # 指定分组的字段
                    'count': {'$sum': 1}
                }
            }
        ]
        res = collection.aggregate(pipeline)
        city = []
        for result in res:
            if result["_id"] != "其他" and result["_id"] != "县":
                city.append(result["_id"])
        newRes = getGeocodes(city)
        print(newRes)
    
    
    # 菜单控制器
    def menuController():
        print(''''
        =======================================
        ||        千锋教育数据爬取系统          ||
        =======================================
        ||请输入你的操作:                      ||
        ||  1.爬取就业信息     2.爬取视频信息    ||
        ||  3.清除所有数据     4.获取就业和课程数据||
        ||  3.清除所有数据     4.退出           ||
        =======================================
        ''')
        while True:
            flag = int(input("请输入你菜单代码:"))
            if flag == 1:
                # 爬取就业信息的代码
                insertDB(2017, 2024)
                log.debug("=======就业信息爬取完毕=======")
                menuController()
            elif (flag == 2):
                # 爬取视频信息部分
                getVieoData()
                log.debug("=======视频爬取完毕=======")
                menuController()
            elif (flag == 3):
                log.debug("=======地理信息格式化中=======")
                formatAddress()
                menuController()
            else:
                log.debug("=======即将退出=======")
                break
    
    
    '''' 【第三部分】主函数部分 '''
    
    
    def main():
        # 开始提示
        log.debug("程序开始")
        # 调用菜单控制器
        menuController()
        # 结束提示
        log.debug("程序执行结束")
    
    
    ''''【第四部分】运行部分 '''
    if __name__ == '__main__':
        main()
    
  • 数据生成.py

    import pandas
    import pymongo
    
    from src.前锋教育可视化.config import *
    
    # 城市参照字典
    contrast = {'金昌市': '甘肃省', '宜宾市': '四川省', '柳州市': '广西壮族自治区', '郴州市': '湖南省', '西宁市': '青海省',
                '丹东市': '辽宁省', '桂林市': '广西壮族自治区', '潍坊市': '山东省', '遵义市': '贵州省',
                '克拉玛依市': '新疆维吾尔自治区', '日照市': '山东省', '阿克苏地区': '新疆维吾尔自治区',
                '六盘水市': '贵州省', '梅州市': '广东省', '商丘市': '河南省', '天门市': '湖北省', '温州市': '浙江省',
                '阿勒泰地区': '新疆维吾尔自治区', '临沂市': '山东省', '池州市': '安徽省', '安庆市': '安徽省',
                '亳州市': '安徽省', '酒泉市': '甘肃省', '舟山市': '浙江省', '深圳市': '广东省', '佳木斯市': '黑龙江省',
                '上海': '上海市', '渭南市': '陕西省', '安阳市': '河南省', '保定市': '河北省', '衡水市': '河北省',
                '沧州市': '河北省', '金华市': '浙江省', '东营市': '山东省', '宜昌市': '湖北省', '泉州市': '福建省',
                '张家界市': '湖南省', '吴忠市': '宁夏回族自治区', '吉林市': '吉林省', '银川市': '宁夏回族自治区',
                '保山市': '云南省', '绍兴市': '浙江省', '河池市': '广西壮族自治区', '郑州市': '河南省',
                '马鞍山市': '安徽省', '龙岩市': '福建省', '河源市': '广东省', '天水市': '甘肃省', '宣城市': '安徽省',
                '南充市': '四川省', '孝感市': '湖北省', '晋中市': '山西省', '怀化市': '湖南省', '黑河市': '黑龙江省',
                '常德市': '湖南省', '大连市': '辽宁省', '佛山市': '广东省', '廊坊市': '河北省', '惠州市': '广东省',
                '常州市': '江苏省', '岳阳市': '湖南省', '许昌市': '河南省', '乌鲁木齐市': '新疆维吾尔自治区',
                '运城市': '山西省', '曲靖市': '云南省', '济宁市': '山东省', '松原市': '吉林省', '秦皇岛市': '河北省',
                '太原市': '山西省', '北京': '北京市', '北海市': '广西壮族自治区', '玉林市': '广西壮族自治区',
                '辽阳市': '辽宁省', '遂宁市': '四川省', '乌兰察布市': '内蒙古自治区', '枣庄市': '山东省',
                '萍乡市': '江西省', '淮南市': '安徽省', '南通市': '江苏省', '鹤壁市': '河南省', '宁德市': '福建省',
                '黄石市': '湖北省', '西安市': '陕西省', '威海市': '山东省', '焦作市': '河南省',
                '黔南布依族苗族自治州': '贵州省', '黄冈市': '湖北省', '贵阳市': '贵州省', '商洛市': '陕西省',
                '成都市': '四川省', '扬州市': '江苏省', '锦州市': '辽宁省', '济源市': '河南省',
                '锡林郭勒盟': '内蒙古自治区', '淮北市': '安徽省', '濮阳市': '河南省', '随州市': '湖北省',
                '莆田市': '福建省', '攀枝花市': '四川省', '固原市': '宁夏回族自治区', '邯郸市': '河北省',
                '湘潭市': '湖南省', '江门市': '广东省', '株洲市': '湖南省', '芜湖市': '安徽省', '资阳市': '四川省',
                '巴中市': '四川省', '玉溪市': '云南省', '泸州市': '四川省', '景德镇市': '江西省', '汉中市': '陕西省',
                '呼伦贝尔市': '内蒙古自治区', '三门峡市': '河南省', '鞍山市': '辽宁省', '张家口市': '河北省',
                '驻马店市': '河南省', '新乡市': '河南省', '福州市': '福建省', '梧州市': '广西壮族自治区',
                '阜阳市': '安徽省', '宿迁市': '江苏省', '邵阳市': '湖南省', '漯河市': '河南省', '荆门市': '湖北省',
                '台州市': '浙江省', '淮安市': '江苏省', '朝阳市': '辽宁省', '荆州市': '湖北省', '汕头市': '广东省',
                '十堰市': '湖北省', '石家庄市': '河北省', '阳江市': '广东省', '济南市': '山东省', '沈阳市': '辽宁省',
                '襄樊市': '湖北省', '镇江市': '江苏省', '烟台市': '山东省', '宿州市': '安徽省', '哈尔滨市': '黑龙江省',
                '长春市': '吉林省', '内江市': '四川省', '咸宁市': '湖北省', '聊城市': '山东省', '贵港市': '广西壮族自治区',
                '云浮市': '广东省', '清远市': '广东省', '牡丹江市': '黑龙江省', '仙桃市': '湖北省',
                '包头市': '内蒙古自治区', '绥化市': '黑龙江省', '武威市': '甘肃省', '广州市': '广东省', '营口市': '辽宁省',
                '崇左市': '广西壮族自治区', '衡阳市': '湖南省', '上饶市': '江西省', '珠海市': '广东省', '兰州市': '甘肃省',
                '临汾市': '山西省', '长沙市': '湖南省', '苏州市': '江苏省', '周口市': '河南省', '盘锦市': '辽宁省',
                '平顶山市': '河南省', '唐山市': '河北省', '南昌市': '江西省', '衢州市': '浙江省', '德阳市': '四川省',
                '咸阳市': '陕西省', '九江市': '江西省', '吐鲁番地区': '新疆维吾尔自治区', '泰州市': '江苏省',
                '眉山市': '四川省', '吉安市': '江西省', '海口市': '海南省', '蚌埠市': '安徽省', '天津': '天津市',
                '洛阳市': '河南省', '鄂尔多斯市': '内蒙古自治区', '赣州市': '江西省', '南京市': '江苏省',
                '六安市': '安徽省', '嘉兴市': '浙江省', '赤峰市': '内蒙古自治区', '昭通市': '云南省', '青岛市': '山东省',
                '海南藏族自治州': '青海省', '三亚市': '海南省', '新余市': '江西省', '绵阳市': '四川省',
                '大理白族自治州': '云南省', '淄博市': '山东省', '宜春市': '江西省', '广元市': '四川省', '德州市': '山东省',
                '榆林市': '陕西省', '阜新市': '辽宁省', '承德市': '河北省', '湘西土家族苗族自治州': '湖南省',
                '邢台市': '河北省', '潮州市': '广东省', '延安市': '陕西省', '丽水市': '浙江省', '拉萨市': '西藏自治区',
                '开封市': '河南省', '朔州市': '山西省', '自贡市': '四川省', '徐州市': '江苏省', '杭州市': '浙江省',
                '毕节地区': '贵州省', '肇庆市': '广东省', '宁波市': '浙江省', '东莞市': '广东省', '晋城市': '山西省',
                '南宁市': '广西壮族自治区', '合肥市': '安徽省', '宝鸡市': '陕西省', '昆明市': '云南省', '重庆': '重庆市',
                '永州市': '湖南省', '湖州市': '浙江省', '大庆市': '黑龙江省', '滨州市': '山东省', '信阳市': '河南省',
                '忻州市': '山西省', '大同市': '山西省', '吕梁市': '山西省', '武汉市': '湖北省', '滁州市': '安徽省',
                '博尔塔拉蒙古自治州': '新疆维吾尔自治区', '长治市': '山西省', '南阳市': '河南省',
                '凉山彝族自治州': '四川省', '湛江市': '广东省', '达州市': '四川省', '葫芦岛市': '辽宁省',
                '盐城市': '江苏省', '连云港市': '江苏省', '无锡市': '江苏省', '呼和浩特市': '内蒙古自治区',
                '通辽市': '内蒙古自治区', '厦门市': '福建省', '中山市': '广东省', '泰安市': '山东省', '庆阳市': '甘肃省'}
    
    # 创建MongoDB连接对象
    client = pymongo.MongoClient(MONGO_URL)
    db = client[MONGO_DB]
    
    
    # 每个专业课程的数量
    def subjectCount():
        list = []
        tables = ["Java基础",
                  "PHP基础",
                  "Python基础",
                  "UI基础",
                  "Unity 3d基础",
                  "go基础",
                  "linux云计算基础",
                  "web前端基础",
                  "大数据基础",
                  "物联网基础",
                  "网络安全基础",
                  "网络营销基础"]
        for t in tables:
            collection = db[t]
            count = collection.count_documents({})
            list.append([t, count])
        return list
    
    
    # 每个专业的播放量
    def subjectStudyNum():
        list = []
        tables = ["Java基础",
                  "PHP基础",
                  "Python基础",
                  "UI基础",
                  "Unity 3d基础",
                  "go基础",
                  "linux云计算基础",
                  "web前端基础",
                  "大数据基础",
                  "物联网基础",
                  "网络安全基础",
                  "网络营销基础"]
        for t in tables:
            count = 0
            collection = db[t]
            items = collection.find({}, {"studyNum": 1})
            for item in items:
                count += item["studyNum"]
            list.append([t, count])
        return list
    
    
    # 各科学习人数占比
    # java的学习人数
    # 每个年份的学生人数
    def yearStudent():
        data = []
        collection = db['student']
        pipeline = [
            {"$addFields": {"date": {"$toDate": "$date"}}},
            {"$group": {"_id": {"year": {"$year": "$date"}}, "count": {"$sum": 1}}},
            {
                "$sort": {"_id": 1}
            }
        ]
        # 执行聚合查询
        results = list(collection.aggregate(pipeline, allowDiskUse=True))
        # 打印结果
        for result in results:
            data.append([result['_id']['year'], result['count']])
        return data
    
    
    # 学历占比
    def educationDuty():
        data = []
        collection = db['student']
        # 定义聚合查询的管道
        pipeline = [
            {
                '$group': {
                    '_id': '$education',  # 指定分组的字段
                    'count': {'$sum': 1}
                }
            },
            {
                "$sort": {"count": 1}
            }
        ]
        res = collection.aggregate(pipeline)
        for i in res:
            data.append([i["_id"], i["count"]])
        return data
    
    
    # 生成省份分布的数据
    def mapCount():
        collection = db['student']
        # 定义聚合查询的管道
        pipeline = [
            {
                '$group': {
                    '_id': '$city',  # 指定分组的字段
                    'count': {'$sum': 1}
                }
            }
        ]
        res = collection.aggregate(pipeline)
        countList = []
        for result in res:
            if result["_id"] in contrast:
                countList.append([contrast[result["_id"]], result["count"]])
        column_names = ['address', 'num']
        table = pandas.DataFrame(countList, columns=column_names)
        grouped = table.groupby("address").sum()
        v1 = table.groupby("address").groups.keys()
        v2 = grouped.iloc[:, 0].tolist()
        # 使用zip函数将两个列表组合为元组的列表,然后使用列表推导式转换为二维列表
        combined_list = [list(item) for item in zip(v1, v2)]
        return combined_list
    
    
  • 图形生成.py

    from pyecharts import options as opts
    from pyecharts.charts import Bar, Pie, Radar, Map
    from pyecharts.commons.utils import JsCode
    from pyecharts.charts import Line
    
    from src.前锋教育可视化.数据生成 import *
    
    ''' 生成对应的图表 '''
    
    
    # 每个专业课程的数量
    def getSubjectCount():
        list = subjectCount()
        res = pandas.DataFrame(list)
        c = (
            Bar(init_opts=opts.InitOpts(width="450px", height="220px"))
            .add_xaxis(res.iloc[:, 0].tolist())
            .add_yaxis("数量", res.iloc[:, 1].tolist())
            .set_global_opts(
                title_opts=opts.TitleOpts(title="各科课程数量",title_textstyle_opts=opts.TextStyleOpts(color="#6495ed")),
                datazoom_opts=opts.DataZoomOpts(),
                legend_opts=opts.LegendOpts(textstyle_opts=opts.TextStyleOpts(color="#00E7F8"))
            )
            .render("各科课程数量.html")
        )
    
    
    # 每个专业的播放量
    def getSubjectStudyNum():
        data = subjectStudyNum()
        res = pandas.DataFrame(data)
        c = (
            Bar(init_opts=opts.InitOpts(width="450px", height="220px"))
            .add_xaxis(res.iloc[:, 0].tolist())
            .add_yaxis("数量", res.iloc[:, 1].tolist(), category_gap="60%")
            .set_series_opts(
                itemstyle_opts={
                    "normal": {
                        "color": JsCode(
                            """new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                        offset: 0,
                        color: 'rgba(0, 244, 255, 1)'
                    }, {
                        offset: 1,
                        color: 'rgba(0, 77, 167, 1)'
                    }], false)"""
                        ),
                        "barBorderRadius": [30, 30, 30, 30],
                        "shadowColor": "rgb(0, 160, 221)",
                    }
                }
            )
            .set_global_opts(title_opts=opts.TitleOpts(title="各科IT课程播放量", title_textstyle_opts=opts.TextStyleOpts(color="#6495ed")),
            legend_opts=opts.LegendOpts(textstyle_opts=opts.TextStyleOpts(color="#00E7F8")))
            .render("各科课程播放量.html")
        )
    
    
    # 各科学习人数占比
    def getStudySubject():
        data = subjectStudyNum()
        res = pandas.DataFrame(data)
        label = res.iloc[:, 0].tolist()
        values = res.iloc[:, 1].tolist()
        c = (
            Pie(init_opts=opts.InitOpts(width="450px", height="220px"))
            .add(
                "",
                [list(z) for z in zip(label, values)],
                radius=["30%", "75%"],
                center=["50%", "50%"],
                rosetype="radius",
            )
            .set_global_opts(
                legend_opts=opts.LegendOpts(is_show=False)
            )
            .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"))  # 值得一提的是,{d}%为百分比
            .render("各科学习人数占比.html")
        )
    
    
    # java的学习人数
    # 每个年份的学生人数
    def getYearStudent():
        data = yearStudent()
        res = pandas.DataFrame(data)
        x_data = ["2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024"]
        y_data = [7639, 10031, 14885, 12661, 13756, 13211, 10967, 1226]
        background_color_js = (
            "new echarts.graphic.LinearGradient(0, 0, 0, 1, "
            "[{offset: 0, color: '#c86589'}, {offset: 1, color: '#06a7ff'}], false)"
        )
        area_color_js = (
            "new echarts.graphic.LinearGradient(0, 0, 0, 1, "
            "[{offset: 0, color: '#eb64fb'}, {offset: 1, color: '#3fbbff0d'}], false)"
        )
    
        c = (
            Line(init_opts=opts.InitOpts(bg_color=JsCode(background_color_js), width="450px", height="220px"))
            .add_xaxis(xaxis_data=x_data)
            .add_yaxis(
                series_name="总量",
                y_axis=y_data,
                is_smooth=True,
                is_symbol_show=True,
                symbol="circle",
                symbol_size=6,
                linestyle_opts=opts.LineStyleOpts(color="#fff"),
                label_opts=opts.LabelOpts(is_show=True, position="top", color="white"),
                itemstyle_opts=opts.ItemStyleOpts(
                    color="red", border_color="#fff", border_width=3
                ),
                tooltip_opts=opts.TooltipOpts(is_show=False),
                areastyle_opts=opts.AreaStyleOpts(color=JsCode(area_color_js), opacity=1),
            )
            .set_global_opts(
                title_opts=opts.TitleOpts(
                    title="学员概况",
                    pos_bottom="0%",
                    pos_left="center",
                    title_textstyle_opts=opts.TextStyleOpts(color="#fff", font_size=16),
                ),
                xaxis_opts=opts.AxisOpts(
                    type_="category",
                    boundary_gap=False,
                    axislabel_opts=opts.LabelOpts(margin=30, color="#ffffff63"),
                    axisline_opts=opts.AxisLineOpts(is_show=False),
                    axistick_opts=opts.AxisTickOpts(
                        is_show=True,
                        length=25,
                        linestyle_opts=opts.LineStyleOpts(color="#ffffff1f"),
                    ),
                    splitline_opts=opts.SplitLineOpts(
                        is_show=True, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f")
                    ),
                ),
                yaxis_opts=opts.AxisOpts(
                    type_="value",
                    position="right",
                    axislabel_opts=opts.LabelOpts(margin=20, color="#ffffff63"),
                    axisline_opts=opts.AxisLineOpts(
                        linestyle_opts=opts.LineStyleOpts(width=2, color="#fff")
                    ),
                    axistick_opts=opts.AxisTickOpts(
                        is_show=True,
                        length=15,
                        linestyle_opts=opts.LineStyleOpts(color="#ffffff1f"),
                    ),
                    splitline_opts=opts.SplitLineOpts(
                        is_show=True, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f")
                    ),
                ),
                legend_opts=opts.LegendOpts(is_show=False),
            )
            .render("每年学生情况.html")
        )
    
    
    # 学历占比
    def getEducationDuty():
        data = educationDuty()
        res = pandas.DataFrame(data)
        v1 = [res.iloc[:, 1].tolist()]
        c = (
            Radar(init_opts=opts.InitOpts(width="450px", height="220px"))
            .add_schema(
                schema=[
                    opts.RadarIndicatorItem(name='博士', max_=100),
                    opts.RadarIndicatorItem(name='硕士', max_=10000),
                    opts.RadarIndicatorItem(name='高中以下', max_=10000),
                    opts.RadarIndicatorItem(name='None', max_=3000),
                    opts.RadarIndicatorItem(name='高中', max_=5000),
                    opts.RadarIndicatorItem(name='专科', max_=47720),
                    opts.RadarIndicatorItem(name='本科', max_=50000),
    
                ]
            )
            .add(
                '学历', v1,
                color='blue',
                # 通过颜色属性 将其填充
                areastyle_opts=opts.AreaStyleOpts(
                    opacity=0.5,
                    color='blue'
                ),
            )
            .set_global_opts(
                legend_opts=opts.LegendOpts(is_show=False)
            )
            .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
            .render("学历雷达图.html")
        )
    
    
    # 生成省份分布的数据
    def chinaMap():
        data = mapCount()
        (
            Map(init_opts=opts.InitOpts(width="920px", height="640px"))
            .add(
                series_name="学员",
                data_pair=data,
                maptype="china",
                # 是否默认选中,默认为True
                # is_selected=True,
                # 是否启用鼠标滚轮缩放和拖动平移,默认为True
                is_roam=True,
                # 是否显示图形标记,默认为True
                is_map_symbol_show=False,
                # 图元样式配置
                itemstyle_opts={
                    # 常规显示
                    "normal": {"areaColor": "white", "borderColor": "red"},
                    # 强调颜色
                    "emphasis": {"areaColor": "pink"}
                }
            )
            # 全局配置项
            .set_global_opts(
                # 设置标题
                title_opts=opts.TitleOpts(title="学员工作分布", title_textstyle_opts=opts.TextStyleOpts(color="#6495ed")),
                legend_opts=opts.LegendOpts(textstyle_opts=opts.TextStyleOpts(color="#00E7F8")),
                # 设置标准显示
                visualmap_opts=opts.VisualMapOpts(max_=20000, is_piecewise=False)
            )
            # 系列配置项
            .set_series_opts(
                # 标签名称显示,默认为True
                label_opts=opts.LabelOpts(is_show=True, color="blue", )
            )
            # 生成本地html文件
            .render("中国地图.html")
        )
    
    
    # 各省薪资分布
    # 最高薪资
    # 过万薪资占比
    # 总人数
    
    ''' 函数执行部分 '''
    getSubjectStudyNum()
    getStudySubject()
    getYearStudent()
    getEducationDuty()
    chinaMap()
    getSubjectCount()
    
  • 启动程序.py

    import webbrowser
    def main():
        url = 'index.html'
        print('''
        ========== 项目启动成功 ==========
        MongoDB的配置,请查看:config.py
        项目爬取和存储过程,请查看:前锋教育数据爬取.py
        数据处理过程,请查看:数据生成.py
        可视化图形生成,请查看:图形生成.py
        启动入口:启动程序.py
        ''')
        webbrowser.open(url)
    
    if __name__ == '__main__':
        main()
    
  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值