转:用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼

简介

想看看你最近一年都在干嘛?看看你平时上网是在摸鱼还是认真工作?想写年度汇报总结,但是苦于没有数据?现在,它来了。

这是一个能让你了解自己的浏览历史的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

接下来,就是我们数据提取最核心的部分了,即从Chrome历史记录文件中提取出我们想要的数据。由于Chrome历史记录文件是一个sqlite数据库,所以我们需要使用数据库语法提取出我们想要的内容。

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
# 获取排序后的历史数据
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'

上面select_statement指的是查询数据库的规则,规则如下:

  1. 从(FROM)表urls中选择(SELECT)出以下字段urls.id, urls.url, urls.title, urls.last_visit_time, urls.visit_count,依次代表URL的IDURL的地址URL的标题URL最后的访问时间URL的访问次数
  2. 接着,从(FROM)表visits中选择(SELECT)出以下字段visits.visit_time, visits.from_visit, visits.transition, visits.visit_duration,分别代表的是访问时间从哪个链接跳转过来的访问跳转访问停留的时间
  3. 步骤1步骤2的结果进行连接,形成一个表格。然后从中(WHERE)筛选出符合urls.id = visits.url的行。在urls中,id代表的是URL的id,在visits中,url代表的也是URL的id,所以只有当两者相等,才能连接一起,才能保留,否则就要去除这一行。
  4. 使用排序函数sorted,这个函数依次是以x[0]x[1]x[2]x[3]x[4]x[5]x[6]x[7]x[8]进行排序,也就是指的是urls.id, urls.url, urls.title, urls.last_visit_time, urls.visit_count, visits.visit_time, visits.from_visit, visits.transition, visits.visit_duration
  5. 返回一个排序好的数据

这里我们列出每个字段代表的意思:

字段名 含义
urls.id url的编号
urls.url url的地址
urls.title url的标题
urls.last_visit_time url的最后访问时间
urls.visit_count url的访问次数
urls.visit_time url的访问时间
urls.from_visit 从哪里访问到这个url
urls.transition url的跳转
urls.visit_duration url的停留时间

6. 如何获取Chrome历史记录文件

  1. 首先,打开浏览器,输入chrome://version/,其中,个人资料路径即为存放历史文件所在的目录。
  2. 跳转到个人资料路径,比如/Users/xxx/Library/Application Support/Google/Chrome/Default,找到一个叫History的文件,这个文件即为历史记录文件。

如何运行

在线演示程序:http://39.106.118.77:8090(普通服务器,勿测压)

运行本程序十分简单,只需要按照以下命令即可运行:

# 跳转到当前目录
cd 目录名
# 先卸载依赖库
pip uninstall -y -r requirement.txt
# 再重新安装依赖库
pip install -r requirement.txt
# 开始运行
python app.py

# 运行成功后,通过浏览器打开http://localhost:8090

原文地址:https://www.cnblogs.com/xxpythonxx/p/11402618.html

时间: 2024-10-31 09:25:16

转:用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼的相关文章

python日志分析

微秒   毫秒 datetime seek定位指针 从行尾到行首 fd.seek(-2,1)  1  当前位置 fd.tell() fd.seek(-2,2)  2   最后位置 fd.tell() fd.seek(0,0)   0  最前位置 read(1)读一位    read() 全部都读 tac与cat    行首到行尾 reversed   翻转字符串 只读一部分    通过时间判断 200 404  503  十分钟之内   第八列  apache.log 1.首先匹配时间格式, D

Python代码分析工具:PyChecker、Pylint

1 概述 PyChecker是Python代码的静态分析工具,它能够帮助查找Python代码的bug,而且能够对代码的复杂度和格式等提出警告. PyChecker可以工作在多种方式之下.首先,PyChecker会导入所检查文件中包含的模块,检查导入是否正确,同时检查文件中的函数.类和方法等. PyChecker可以检查出来的问题有如下几种: 全局量没有找到,比如没有导入模块 传递给函数.方法.构造器的参数数目错误 传递给内建函数和方法的参数数目错误 字符串格式化信息不匹配 使用不存在的类方法和属

Python性能分析指南(未完成)

英文原文:http://www.huyng.com/posts/python-performance-analysis/ 译文:http://www.oschina.net/translate/python-performance-analysis 虽然你所写的每个Python程序并不总是需要严密的性能分析,但是当这样的问题出现时,如果能知道Python生态系统中的许多种工具,这样总是可以让人安心的. 分析一个程序的性能可以归结为回答4个基本的问题: 1.它运行的有多块? 2.那里是速度的瓶颈?

第五次作业——python效能分析与几个问题(个人作业)

第五次作业--效能分析与几个问题(个人作业) 前言 阅读了大家对于本课程的目标和规划之后,想必很多同学都跃跃欲试,迫不及待想要提高自身实践能力,那么就从第一个个人项目开始吧,题目要求见下. 阅读 阅读<构建之法>第一章至第三章的内容,并在下方作业里体现出阅读后的成果.特别是第2章中的效能分析及个人软件开发流程(PSP). 参考文章: <构建之法>教学笔记--Python中的效能分析与几个问题 四则运算器效能分析 软工第2次作业-四则运算器 题目描述 可以选择以下题目(或者自主选择题

Python大佬分析了15万歌词,告诉你民谣歌手们到底在唱什么

前几天小编写了两篇利用Python采集网易云歌词和采集网易云音乐歌曲文章,相信小伙伴们经过实践之后都能够顺利的采集到自己想要听的歌曲.下面的歌词是小编去年11月份采集的民谣歌词,经过统计,歌词量达到将近15万. 用Python采集的民谣歌词 心血来潮,想利用Python来分析一下民谣歌手们到底在唱些什么鬼~~ 首先运用jieba库进行分词和词频统计分析,得到歌词中的词频统计,部分主要代码如下图所示: 运用jieba库进行分词和词频统计分析 得到的词频后将其导入到Excel表格中,详情如下图: 民

Python性能分析

Python性能分析 https://www.cnblogs.com/lrysjtu/p/5651816.html https://www.cnblogs.com/cbscan/articles/3341231.html 使用ipdb 使用profile import profile def profileTest(): Total =1; for i in range(10): Total=Total*(i+1) print Total return Total if __name__ ==

Python性能分析工具Profile

Python性能分析工具Profile 代码优化的前提是需要了解性能瓶颈在什么地方,程序运行的主要时间是消耗在哪里,对于比较复杂的代码可以借助一些工具来定位,python 内置了丰富的性能分析工具,如 profile,cProfile 与 hotshot 等.其中 Profiler 是 python 自带的一组程序,能够描述程序运行时候的性能,并提供各种统计帮助用户定位程序的性能瓶颈.Python 标准模块提供三种 profilers:cProfile,profile 以及 hotshot. p

从python中copy与deepcopy的区别看python引用

讨论copy与deepcopy的区别这个问题要先搞清楚python中的引用.python的内存管理. python中的一切事物皆为对象,并且规定参数的传递都是对象的引用.可能这样说听起来比较难懂,对比一下PHP中的赋值和引用就有大致的概念了.参考下面一段引用: 1. python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是“传对象引用”的方式.实际上,这种方式相当于传值和传引用的一种综合.如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当

python气象分析

数据分析实例 -- 气象数据 一.实验介绍 本实验将对意大利北部沿海地区的气象数据进行分析与可视化.我们在实验过程中先会运用 Python 中matplotlib库的对数据进行图表化处理,然后调用 scikit-learn 库当中的的 SVM 库对数据进行回归分析,最终在图表分析的支持下得出我们的结论. 1.1 课程来源 本课程基于 图灵教育 的 <Python数据分析实战> 第2章制作,感谢 图灵教育 授权实验楼发布.如需系统的学习本书,请购买<Python数据分析实战>. 为了