简介

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

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

该函数的代码流程为:

连接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'

该函数的代码流程为:

设置数据库查询语句select_statement,调用query_sqlite_db()函数,获取解析后的历史记录文件数据。并对返回后的历史记录数据文件按照不同元素规则进行排序。至此,经过排序的解析后的历史记录数据文件获取成功。

3. web服务器基本配置

与web服务器基本配置有关的文件为app_configuration.py和app.py文件。包括设置web服务器的端口号,访问权限,静态资源目录等。

4. 前端页面部署

与前端部署有关的文件为app_layout.py和app_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

该函数的代码流程为:

首先,对解析完数据库文件后返回的history_data进行遍历,获得url数据,并调用url_simplification(url)对齐进行简化。接着,依次将简化后的url存入字典中。

调用get_top_k_from_dict(dict_data, k),从字典dict_data中获取前k个最大值的数据。

接着,开始绘制柱状图了。使用go.Bar()绘制柱状图,其中,x和y代表的是属性和属性对应的数值,为list格式。xaxis和yaxis`分别设置相应坐标轴的标题

返回一个figure对象,以便于传输给前端。

而assets目录下包含的数据为image和css,都是用于前端布局。

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")

该函数的代码流程为:

首先确定好输入是什么(触发回调的数据),输出是什么(回调输出的数据),需要带上什么数据。dash.dependencies.Input指的是触发回调的数据,而dash.dependencies.Input('input_website_count_rank', 'value')表示当id为input_website_count_rank的组件的value发生改变时,会触发这个回调。而该回调经过update(value, store_memory_history_data)的结果会输出到id为graph_website_count_rank的value,通俗来讲,就是改变它的值。

对于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

该函数的代码流程为:

首先判断用户上传的数据contents是否不为空,接着将客户端上传的文件进行base64解码。并且,为客户端上传的文件添加后缀,防止文件重复覆盖,最终将客户端上传的文件写入本地磁盘文件。

写入完毕后,使用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指的是查询数据库的规则,规则如下:

从(FROM)表urls中选择(SELECT)出以下字段urls.id, urls.url, urls.title, urls.last_visit_time, urls.visit_count,依次代表URL的ID,URL的地址,URL的标题,URL最后的访问时间,URL的访问次数。

接着,从(FROM)表visits中选择(SELECT)出以下字段visits.visit_time, visits.from_visit, visits.transition, visits.visit_duration,分别代表的是访问时间,从哪个链接跳转过来的,访问跳转,访问停留的时间。

对步骤1和步骤2的结果进行连接,形成一个表格。然后从中(WHERE)筛选出符合urls.id = visits.url的行。在urls中,id代表的是URL的id,在visits中,url代表的也是URL的id,所以只有当两者相等,才能连接一起,才能保留,否则就要去除这一行。

使用排序函数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。

返回一个排序好的数据

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

字段名

含义

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历史记录文件

首先,打开浏览器,输入chrome://version/,其中,个人资料路径即为存放历史文件所在的目录。

跳转到个人资料路径,比如/Users/xxx/Library/Application Support/Google/Chrome/Default,找到一个叫History的文件,这个文件即为历史记录文件。

如何运行

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

# 跳转到当前目录

cd 目录名

# 先卸载依赖库

pip uninstall -y -r requirement.txt

# 再重新安装依赖库

pip install -r requirement.txt

# 开始运行

python app.py

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

python上网行为分析_转:用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼...相关推荐

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

    简介 想看看你最近一年都在干嘛?看看你平时上网是在摸鱼还是认真工作?想写年度汇报总结,但是苦于没有数据?现在,它来了. 这是一个能让你了解自己的浏览历史的Chrome浏览历史记录分析程序,当然了,他仅 ...

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

    2019 AI ProCon"598元学生票"限量抢购中!3日通票团购倒计时6天,扫码查看▲ 作者 | 云外孤岛 出自 | Python那些事(ID:pPythonSomethin ...

  3. python注册人工智能专业_从专业程度上分析Python和人工智能(AI) 它们如何相关?...

    Python和人工智能(AI) - 它们如何相关? Python是当今开发人员使用的最流行的编程语言之一.Guido Van Rossum于1991年创建它,自成立以来,它一直是使用最广泛的语言之一, ...

  4. 泰坦尼克号python数据分析统计服_数据分析可视化——泰坦尼克号幸存者分析(上)...

    文章目录数据获取.结构分析如何获取seaborn提供数据源 特征列分析 缺失值与数据清洗年龄缺失值处理 填充embarked 删除不必要的列 幸存者分析分析性别对存活率的影响 分析年龄对存活率影响 分 ...

  5. python pdf解析毕业论文_电影数据读取、分析与展示毕业论文+任务书+Python项目源码...

    摘  要 Python为网页数据爬取和数据分析提供了很多工具包.基于Python的BeautifulSoup可以快速高效地爬取网站数据,Pandas工具能方便灵活地清洗分析数据,调用Python的Ma ...

  6. python金融量化书籍_超强干货 | Python金融数据量化分析教程+机器学习电子书

    如今Python语言的学习已经上升到了国家战略的层面上.Python语言是人工智能的基础语言,国家相关教育部门对于"人工智能普及"格外重视,不仅将Python列入到小学.中学和高中 ...

  7. 如何用python抓取文献_浅谈Python爬虫技术的网页数据抓取与分析

    浅谈 Python 爬虫技术的网页数据抓取与分析 吴永聪 [期刊名称] <计算机时代> [年 ( 卷 ), 期] 2019(000)008 [摘要] 近年来 , 随着互联网的发展 , 如何 ...

  8. 如何用python爬取数据_如何使用python爬取知乎数据并做简单分析

    原标题:如何使用python爬取知乎数据并做简单分析 一.使用的技术栈: 爬虫:python27 +requests+json+bs4+time 分析工具: ELK套件 开发工具:pycharm 数据 ...

  9. python商品打折问题_电商打折套路分析 —— Python数据分析练习

    电商打折套路分析 --2016天猫双十一美妆数据分析 数据简介 此次分析的数据来自于城市数据团对2016年双11天猫数据的采集和整理,原始数据为.xlsx格式 包括update_time/id/tit ...

最新文章

  1. 皮一皮:这个职业是我想得那样吗?
  2. mysql栈空间大小_jvm 堆内存 栈内存 大小设置
  3. 使用netty搭建一个简单的聊天室
  4. 限制外来计算机访问,准入网关|网络准入控制|非法接入检测|限制非法访问解决方案...
  5. 00截断上传绕过_小谈截断上传漏洞
  6. java自定义分页标签_自定义分页标签--仿javaeye分页效果
  7. C#LeetCode刷题之#383-赎金信(Ransom Note)
  8. Python机器学习:多项式回归与模型泛化003过拟合与欠拟合
  9. 你的 AI 程序无人问津?不是不够好,而是缺一个展示的舞台
  10. LeetCode 150. Evaluate Reverse Polish Notation
  11. SELECT中的多表连接
  12. liunx 下mysql 的安装
  13. 抖音小店商品如何挂到精选联盟上面?带货有什么技巧方法?
  14. 43_sql注入绕waf
  15. 内核tty框架_串口_tty_shell的关系
  16. 微信被误封号怎么办?详解微信封号的底层逻辑
  17. java中public,private,protect,default区别
  18. P1772 [ZJOI2006]物流运输(线性dp+最短路径)
  19. 机器学习系列5-梯度下降法
  20. Scrapy + Selenium 实现模拟登录,获取页面动态加载数据

热门文章

  1. springBoot使用redis获取自增序号
  2. SpringCloud-Gateway之RoutePredicateFactory
  3. Android Studio 在MuMu模拟器上实现 xposed简单劫持
  4. 复变函数与积分变换(一)学习笔记[复数的概念性质与常见的三角表达式]
  5. mipi DPHY时序讲解
  6. MIGO 行项目屏幕自定义字段增强示例
  7. python画条形图并分类-python matplotlib库绘制条形图练习题
  8. git 贮藏弹出报错
  9. 卡巴斯基KIS的激活方法
  10. 简单理解:人工智能、数据挖掘、模式识别、机器学习、深度学习