1. 程式人生 > >MOOC課程資訊D3.js動態視覺化

MOOC課程資訊D3.js動態視覺化

版權宣告:本文為博主原創文章,轉載 請註明出處:https://blog.csdn.net/sc2079/article/details/83153693

- 寫在前面



  好久沒更新部落格了,主要還是最近太忙了。很久之前就看到B站上動態柱狀圖圖表(用D3.js做的),詳情見@Jannchie見齊的主頁。感覺很不錯,於是便自己也做一哈。正好前一陣子寫了指令碼對中國大學MOOC的課程資訊進行了爬取,經過修改後弄成了定時爬蟲。經過近一個月爬取,資料已經挺多的啦,可以開始類似動態展示了。

  如果需要查閱爬蟲指令碼的,可參見我的部落格:

  中國大學MOOC課程資訊爬取與資料儲存

- 環境配置



  執行環境:Python3.6、Spyder
  依賴的模組:pandas、mysql等

- 開始工作


1. 資料


  從9月20日至今,已有28張表格(以爬取日期命名),每張表格中都有一兩千條課程資料,如下:

2. 開源動態視覺化專案


  下載開源專案

  Historical-ranking-data-visualization-based-on-d3.js

  解壓開啟後,可以看到示例的example檔案




  步驟很簡單,只需根據示例檔案格式新增資料即可。對於比較複雜的設定,如新增頂部附加資訊或自定義顏色等,開啟config,js和visual.js進行相應修改。

  開啟壓縮包內的bargraph.html網頁並新增待視覺化的表格檔案即可。

3. 獲取每天選課熱度前10課程

'''獲取熱度每天選課熱度前15課程'''
def get_top_hot(quire_condition):
    db = pymysql.connect(host='localhost',user='root',passwd='root',db='mooc_courses_infos',charset='utf8')    #連線資料庫
    cur = db.cursor()
    sql = 'SHOW TABLES'
    cur.execute(sql)    #遍歷所有表格
    tables= cur.fetchall()
    top_hot={}  #熱度
    for table in tables:
        data=table[0][9:11]+'-'+table[0][12:14]  #日期標準化
        cur.execute("select course,id,stu_num from %s"% table+" where start_time like '%s'"% quire_condition+" ORDER BY stu_num desc limit 10")  
        result=cur.fetchall()
        top_hot[data]=result
    return top_hot
'''熱度top10課程寫入CSV表格'''
def save_csv(subject,top_hot):
    all_data=()   #所有資料初始化
    date=[]     #日期
    order=[]    #每日熱度排名
    for data in top_hot:  
        _order=[i+1 for i in range(len(top_hot[data]))]  #每日排名編號
        order.extend(_order)
        all_data+=top_hot[data] #新增資料 
        date.extend([data for _ in top_hot[data]])  #日期
    dataframe = pd.DataFrame(list(all_data))  #資料字典化
    dataframe.columns = ['name','type','value']  #修改標籤
    dataframe['type']=order  #將type列值改為每日熱度的排名
    dataframe['date']=date   #新增日期列 
    path='C:\\Users\\Administrator\\Desktop\\Historical-ranking-data-visualization-based-on-d3.js-master\\src\\'
    '''將DataFrame儲存為csv,index表示是否顯示行名,default=True'''
    dataframe.to_csv(path+subject+'.csv',index=False,sep=',')  #寫入csv

  需要說明的是因為課程程序不一致,為了相對公正一些,我這裡將其分為三類:已結束的、正在進行的、即將開始的,分別獲取每日熱度top10。
conditions={'已結束':'已結束%','即將開始':'%開課%','正在進行':'進行至%'}  #查詢條件集
condition='已結束'  #查詢條件
quire_condition=conditions[condition]  #SQL語句中的查詢條件
top_hot=get_top_hot(quire_condition)  #獲取指定查詢條件下所有課程熱度前10
save_csv(condition,top_hot)  #存入SCV表格

4. 獲取指定課程門類下每天選課熱度前10課程

'''獲取指定門類課程名稱和ID'''
def get_kc_kind(subject): 
    subject_ids=[]
    db = pymysql.connect(host='localhost',user='root',passwd='root',db='mooc_courses_info2',charset='utf8')
    cur = db.cursor()
    cur.execute("select id from %s"% subject)    #獲取表所有課程ID
    results=cur.fetchall()
    for result in results:
        subject_ids.append(result[0])
    return subject_ids
'''獲取指定門類課程的選課人數變化'''
def get_hot_by_subject(subject_ids): 
    subject_ids=tuple(subject_ids)
    db = pymysql.connect(host='localhost',user='root',passwd='root',db='mooc_courses_infos',charset='utf8')
    cur = db.cursor()
    sql = 'SHOW TABLES'
    cur.execute(sql)   #遍歷指定資料庫所有表
    tables= cur.fetchall()
    top_hot={}  #熱度
    for table in tables:  #特定日期
        data=table[0][9:11]+'-'+table[0][12:14]  #日期標準化
        '''查詢條件:在指定門類下ID範圍內;正在進行的課程;課程熱度由高到低前10'''
        sql2 = "select course,id,stu_num from %s"% table+" where id in (%s)" % ','.join(['%d']*len(subject_ids)) % subject_ids \
              +" and start_time like '進行至%' ORDER BY stu_num desc limit 10"
        cur.execute(sql2)
        result=cur.fetchall()
        top_hot[data]=result
    return top_hot


  這裡值得說的是SQL查詢語句where in下變數的表達,使用了format(花了不少功夫才得以解決)。

subjects={'國家精品':'excellent_course','計算機':'computer','經濟管理':'management','心理學':'psychology',
         '外語':'language','文學歷史':'literary_history','藝術設計':'art','工學':'engineering',
         '理學':'science','生命科學':'biomedicine','哲學':'philosophy','法學':'law',
         '教育教學':'teaching_method'}
_subjects=list(subjects.keys())  #課程門類中文名列表
for subject in _subjects:
    subject_Eng=subjects[subject]  #課程門類英文名
    subject_ids=get_kc_kind(subject_Eng)  #獲取該門類下所有ID
    subject_top_hot=get_hot_by_subject(subject_ids)  #該門類下每日課程熱度前10
    save_csv(subject,subject_top_hot)  #寫入CSV

- 結果展示


1. 正在進行的所有課程每日熱度前10

2. 即將開課的所有課程每日熱度前10

3. 已結束的所有課程每日熱度前10

4. 計算機門類下正在進行課程每日熱度前10

5. 國家精品門類下正在進行課程每日熱度前10

- 寫在最後



  執行程式時發現挺快的,只有幾秒鐘,因此程式碼優化暫時不著急做。在繪製動態圖表時,為了展示效果更好還需要學習下開源專案的程式碼,進行相應優化提升。另圖表中有些Bug,比如有些值顯示不出來,為NaN。

  最後還是非常感謝大佬的開源奉獻!