1. 程式人生 > >一鍵分析你的上網行為, 看看你平時上網都在幹嘛?

一鍵分析你的上網行為, 看看你平時上網都在幹嘛?

目錄

  • 一鍵分析你的上網行為, 看看你平時上網都在幹嘛?
    • 簡介
    • 部分截圖
    • 程式碼思路
    • 如何執行
    • 補充

一鍵分析你的上網行為, 看看你平時上網都在幹嘛?

簡介

想看看你最近一年都在幹嘛?看看你平時上網是在摸魚還是認真工作?想寫年度彙報總結,但是苦於沒有資料?現在,它來了。

這是一個能讓你瞭解自己的瀏覽歷史的Chrome瀏覽歷史記錄分析程式,當然了,他僅適用於Chrome瀏覽器或者以Chrome為核心的瀏覽器。

在該頁面中你將可以檢視有關自己在過去的時間裡所訪問瀏覽的域名、URL以及忙碌天數的前十排名以及相關的資料圖表。




部分截圖




程式碼思路

1. 目錄結構

首先,我們先看一下整體目錄結構

Code
├─ app_callback.py                          回撥函式,實現後臺功能
├─ app_configuration.py                     web伺服器配置
├─ app_layout.py                            web前端頁面配置
├─ app_plot.py                              web圖表繪製
├─ app.py                                   web伺服器的啟動
├─ assets                                   web所需的一些靜態資原始檔
│  ├─ css                                   web前端元素佈局檔案
│  │  ├─ custum-styles_phyloapp.css
│  │  └─ stylesheet.css
│  ├─ image                                 web前端logo圖示
│  │  ├─ GitHub-Mark-Light.png
│  └─ static                                web前端幫助頁面
│  │  ├─ help.html
│  │  └─ help.md
├─ history_data.py                          解析chrome歷史記錄檔案
└─ requirement.txt                          程式所需依賴庫
  • app_callback.py
    該程式基於python,使用dash web輕量級框架進行部署。app_callback.py主要用於回撥,可以理解為實現後臺功能。

  • app_configuration.py
    顧名思義,對web伺服器的一些配置操作。

  • app_layout..py
    web前端頁面配置,包含html, css元素。

  • app_plot.py
    這個主要是為實現一些web前端的圖表資料。

  • app.py
    web伺服器的啟動。

  • assets
    靜態資源目錄,用於儲存一些我們所需要的靜態資源資料。

  • history_data.py
    通過連線sqlite資料庫,並解析Chrome歷史記錄檔案。

  • requirement.txt

    執行本程式所需要的依賴庫。


2. 解析歷史記錄檔案資料

與解析歷史記錄檔案資料有關的檔案為history_data.py檔案。我們一一分析。

# 查詢資料庫內容
def query_sqlite_db(history_db, query):

    # 查詢sqlite資料庫
    # 注意,History是一個檔案,沒有後綴名。它不是一個目錄。
    conn = sqlite3.connect(history_db)
    cursor = conn.cursor()

    # 使用sqlite檢視軟體,可清晰看到表visits的欄位url=表urls的欄位id
    # 連線表urls和visits,並獲取指定資料
    select_statement = query

    # 執行資料庫查詢語句
    cursor.execute(select_statement)

    # 獲取資料,資料格式為元組(tuple)
    results = cursor.fetchall()

    # 關閉
    cursor.close()
    conn.close()

    return results

該函式的程式碼流程為:

  1. 連線sqlite資料庫,執行查詢語句,返回查詢結構,最終關閉資料庫連線。
# 獲取排序後的歷史資料
def get_history_data(history_file_path):

    try:

        # 獲取資料庫內容
        # 資料格式為元組(tuple)
        select_statement = "SELECT urls.id, urls.url, urls.title, urls.last_visit_time, urls.visit_count, visits.visit_time, visits.from_visit, visits.transition, visits.visit_duration FROM urls, visits WHERE urls.id = visits.url;"
        result = query_sqlite_db(history_file_path, select_statement)

        # 將結果按第1個元素進行排序
        # sort和sorted內建函式會優先排序第1個元素,然後再排序第2個元素,依此類推
        result_sort = sorted(result, key=lambda x: (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]))

        # 返回排序後的資料
        return result_sort
    except:
        # print('讀取出錯!')
        return 'error'

該函式的程式碼流程為:

  1. 設定資料庫查詢語句select_statement,呼叫query_sqlite_db()函式,獲取解析後的歷史記錄檔案資料。並對返回後的歷史記錄資料檔案按照不同元素規則進行排序。至此,經過排序的解析後的歷史記錄資料檔案獲取成功。


3. web伺服器基本配置

與web伺服器基本配置有關的檔案為app_configuration.pyapp.py檔案。包括設定web伺服器的埠號,訪問許可權,靜態資源目錄等。


4. 前端頁面部署

與前端部署有關的檔案為app_layout.pyapp_plot.py以及assets目錄。

前端佈局主要包括以下幾個元素:

  • 上傳歷史記錄檔案元件
  • 繪製頁面訪問次陣列件
  • 繪製頁面訪問停留總時間排名元件
  • 每日頁面訪問次數散點圖元件
  • 某日不同時刻訪問次數散點圖元件
  • 訪問次數最多的10個URL元件
  • 搜尋關鍵詞排名元件
  • 搜尋引擎使用情況元件

app_layout.py中,這些元件的配置大多一樣,和平常的html, css配置一樣,所以我們僅僅以配置頁面訪問次數排名元件為例子。

# 頁面訪問次數排名
html.Div(
    style={'margin-bottom':'150px'},
    children=[
        html.Div(
            style={'border-top-style':'solid','border-bottom-style':'solid'},
            className='row',
            children=[
                html.Span(
                    children='頁面訪問次數排名, ',
                    style={'font-weight': 'bold', 'color':'red'}
                ),

                html.Span(
                    children='顯示個數:',
                ),
                dcc.Input(
                    id='input_website_count_rank',
                    type='text',
                    value=10,
                    style={'margin-top':'10px', 'margin-bottom':'10px'}
                ),
            ]
        ),


        html.Div(
            style={'position': 'relative', 'margin': '0 auto', 'width': '100%', 'padding-bottom': '50%', },
            children=[
                dcc.Loading(
                    children=[
                        dcc.Graph(
                            id='graph_website_count_rank',
                            style={'position': 'absolute', 'width': '100%', 'height': '100%', 'top': '0',
                                   'left': '0', 'bottom': '0', 'right': '0'},
                            config={'displayModeBar': False},
                        ),
                    ],
                    type='dot',
                    style={'position': 'absolute', 'top': '50%', 'left': '50%', 'transform': 'translate(-50%,-50%)'}
                ),
            ],
        )
    ]
)

可以看到,雖然是python編寫的,但是隻要具備前端經驗的人,都可以輕而易舉地在此基礎上新增或者刪除一些元素,所以我們就不詳細講如何使用html和css了。

app_plot.py中,主要是以繪製圖表相關的。使用的是plotly庫,這是一個用於具有web互動的畫圖元件庫。
這裡以繪製頁面訪問頻率排名 柱狀圖為例子,講講如何使用plotly庫進行繪製。

# 繪製 頁面訪問頻率排名 柱狀圖
def plot_bar_website_count_rank(value, history_data):

    # 頻率字典
    dict_data = {}

    # 對歷史記錄檔案進行遍歷
    for data in history_data:
        url = data[1]
        # 簡化url
        key = url_simplification(url)

        if (key in dict_data.keys()):
            dict_data[key] += 1
        else:
            dict_data[key] = 0

    # 篩選出前k個頻率最高的資料
    k = convert_to_number(value)
    top_10_dict = get_top_k_from_dict(dict_data, k)

    figure = go.Figure(
        data=[
            go.Bar(
                x=[i for i in top_10_dict.keys()],
                y=[i for i in top_10_dict.values()],
                name='bar',
                marker=go.bar.Marker(
                    color='rgb(55, 83, 109)'
                )
            )
        ],
        layout=go.Layout(
            showlegend=False,
            margin=go.layout.Margin(l=40, r=0, t=40, b=30),
            paper_bgcolor='rgba(0,0,0,0)',
            plot_bgcolor='rgba(0,0,0,0)',
            xaxis=dict(title='網站'),
            yaxis=dict(title='次數')
        )
    )


    return figure

該函式的程式碼流程為:

  1. 首先,對解析完資料庫檔案後返回的history_data進行遍歷,獲得url資料,並呼叫url_simplification(url)對齊進行簡化。接著,依次將簡化後的url存入字典中。
  2. 呼叫get_top_k_from_dict(dict_data, k),從字典dict_data中獲取前k個最大值的資料。
  3. 接著,開始繪製柱狀圖了。使用go.Bar()繪製柱狀圖,其中,xy代表的是屬性和屬性對應的數值,為list格式xaxisyaxis`分別設定相應座標軸的標題
  4. 返回一個figure物件,以便於傳輸給前端。

assets目錄下包含的資料為imagecss,都是用於前端佈局。


5. 後臺部署

與後臺部署有關的檔案為app_callback.py檔案。這個檔案使用回撥的方式對前端頁面佈局進行更新。

首先,我們看看關於頁面訪問頻率排名的回撥函式:


# 頁面訪問頻率排名
@app.callback(
    dash.dependencies.Output('graph_website_count_rank', 'figure'),
    [
        dash.dependencies.Input('input_website_count_rank', 'value'),
        dash.dependencies.Input('store_memory_history_data', 'data')
    ]
)
def update(value, store_memory_history_data):

    # 正確獲取到歷史記錄檔案
    if store_memory_history_data:
        history_data = store_memory_history_data['history_data']
        figure = plot_bar_website_count_rank(value, history_data)
        return figure
    else:
        # 取消更新頁面資料
        raise dash.exceptions.PreventUpdate("cancel the callback")

該函式的程式碼流程為:

  1. 首先確定好輸入是什麼(觸發回撥的資料),輸出是什麼(回撥輸出的資料),需要帶上什麼資料。dash.dependencies.Input指的是觸發回撥的資料,而dash.dependencies.Input('input_website_count_rank', 'value')表示當idinput_website_count_rank的元件的value發生改變時,會觸發這個回撥。而該回調經過update(value, store_memory_history_data)的結果會輸出到idgraph_website_count_rankvalue,通俗來講,就是改變它的值。
  2. 對於def update(value, store_memory_history_data)的解析。首先是判斷輸入資料store_memory_history_data是否不為空物件,接著讀取歷史記錄檔案history_data,接著呼叫剛才所說的app_plot.py檔案中的plot_bar_website_count_rank(),返回一個figure物件,並將這個物件返回到前端。至此,前端頁面的佈局就會顯示出頁面訪問頻率排名的圖表了。

還有一個需要說的就是關於上次檔案的過程,這裡我們先貼出程式碼:

# 上傳檔案回撥
@app.callback(

    dash.dependencies.Output('store_memory_history_data', 'data'),
    [
        dash.dependencies.Input('dcc_upload_file', 'contents')
    ]
)
def update(contents):

    if contents is not None:

        # 接收base64編碼的資料
        content_type, content_string = contents.split(',')

        # 將客戶端上傳的檔案進行base64解碼
        decoded = base64.b64decode(content_string)

        # 為客戶端上傳的檔案新增字尾,防止檔案重複覆蓋
        # 以下方式確保檔名不重複
        suffix = [str(random.randint(0,100)) for i in range(10)]
        suffix = "".join(suffix)
        suffix = suffix + str(int(time.time()))

        # 最終的檔名
        file_name = 'History_' + suffix
        # print(file_name)

        # 建立存放檔案的目錄
        if (not (exists('data'))):
            makedirs('data')

        # 欲寫入的檔案路徑
        path = 'data' + '/' + file_name

        # 寫入本地磁碟檔案
        with open(file=path, mode='wb+') as f:
            f.write(decoded)


        # 使用sqlite讀取本地磁碟檔案
        # 獲取歷史記錄資料
        history_data = get_history_data(path)
        
        # 獲取搜尋關鍵詞資料
        search_word = get_search_word(path)

        # 判斷讀取到的資料是否正確
        if (history_data != 'error'):
            # 找到
            date_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
            print('新接收到一條客戶端的資料, 資料正確, 時間:{}'.format(date_time))
            store_data = {'history_data': history_data, 'search_word': search_word}
            return store_data
        else:
            # 沒找到
            date_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
            print('新接收到一條客戶端的資料, 資料錯誤, 時間:{}'.format(date_time))
            return  None

    return None

該函式的程式碼流程為:

  1. 首先判斷使用者上傳的資料contents是否不為空,接著將客戶端上傳的檔案進行base64解碼。並且,為客戶端上傳的檔案新增字尾,防止檔案重複覆蓋,最終將客戶端上傳的檔案寫入本地磁碟檔案。

  2. 寫入完畢後,使用sqlite讀取本地磁碟檔案,若讀取正確,則返回解析後的資料,否則返回None




如何執行

線上演示程式:http://39.106.118.77:8090(普通伺服器,勿測壓)

執行本程式十分簡單,只需要按照以下命令即可執行:

# 跳轉到當前目錄
cd 目錄名
# 先解除安裝依賴庫
pip uninstall -y -r requirement.txt
# 再重新安裝依賴庫
pip install -r requirement.txt
# 開始執行
python app.py

# 執行成功後,通過瀏覽器開啟http://localhost:8090




補充

完整版原始碼存放在github上,有需要的可以下載

專案持續更新,歡迎您star本專案