python上网行为分析_用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼...
原标题:用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼
关注
作者:云外孤鸟
https://www.cnblogs.com/cloudbird/p/11336663.html
简介
想看看你最近一年都在干嘛?看看你平时上网是在摸鱼还是认真工作?想写年度汇报总结,但是苦于没有数据?现在,它来了。
这是一个能让你了解自己的浏览历史的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文件。我们一一分析。
# 查询数据库内容
defquery_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
returnresults
该函数的代码流程为:
连接sqlite数据库,执行查询语句,返回查询结构,最终关闭数据库连接。
# 获取排序后的历史数据
defget_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= lambdax: (x[ 0], x[ 1], x[ 2], x[ 3], x[ 4], x[ 5], x[ 6], x[ 7], x[ 8]))
# 返回排序后的数据
returnresult_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库进行绘制。
# 绘制 页面访问频率排名 柱状图
defplot_bar_website_count_rank(value, history_data):
# 频率字典
dict_data = {}
# 对历史记录文件进行遍历
fordata inhistory_data:
url = data[ 1]
# 简化url
key = url_simplification(url)
if(key indict_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 fori intop_10_dict.keys],
y=[i fori intop_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= '次数')
)
)
returnfigure
该函数的代码流程为:
首先,对解析完数据库文件后返回的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')
]
)
defupdate(value, store_memory_history_data):
# 正确获取到历史记录文件
ifstore_memory_history_data:
history_data = store_memory_history_data[ 'history_data']
figure = plot_bar_website_count_rank(value, history_data)
returnfigure
else:
# 取消更新页面数据
raisedash.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')
]
)
defupdate(contents):
ifcontents isnotNone:
# 接收base64编码的数据
content_type, content_string = contents.split( ',')
# 将客户端上传的文件进行base64解码
decoded = base64.b64decode(content_string)
# 为客户端上传的文件添加后缀,防止文件重复覆盖
# 以下方式确保文件名不重复
suffix = [str(random.randint( 0, 100)) fori inrange( 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
# 写入本地磁盘文件
withopen(file=path, mode= 'wb+') asf:
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}
returnstore_data
else:
# 没找到
date_time = time.strftime( '%Y-%m-%d %H:%M:%S', time.localtime(time.time))
print( '新接收到一条客户端的数据, 数据错误, 时间:{}'.format(date_time))
returnNone
returnNone
该函数的代码流程为:
首先判断用户上传的数据contents 是否不为空,接着将客户端上传的文件进行base64解码。并且,为客户端上传的文件添加后缀,防止文件重复覆盖,最终将客户端上传的文件写入本地磁盘文件。
写入完毕后,使用sqlite读取本地磁盘文件,若读取正确,则返回解析后的数据,否则返回None
接下来,就是我们数据提取最核心的部分了,即从Chrome历史记录文件中提取出我们想要的数据。由于Chrome历史记录文件是一个sqlite数据库,所以我们需要使用数据库语法提取出我们想要的内容。
# 获取排序后的历史数据
defget_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= lambdax: (x[ 0], x[ 1], x[ 2], x[ 3], x[ 4], x[ 5], x[ 6], x[ 7], x[ 8]))
# 返回排序后的数据
returnresult_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历史记录文件
Windows Vista, Windows 7, Windows 8, Windows 10
历史记录文件位置:
C:Users%USERNAME%AppDataLocalGoogleChromeUser DataDefaultHistory
拷贝历史记录文件到桌面:
bash # 打开命令行cmd,输入以下命令, 自动将History文件复制到桌面, 文件名为History, 没有后缀名 copy "C:Users%USERNAME%AppDataLocalGoogleChromeUser DataDefaultHistory" "C:Users%USERNAME%DesktopHistory"
注意说明:%USERNAME% 为你的用户名, 如果执行命令出现错误, 请手动找到该历史记录文件。
Windows XP
历史记录文件位置:
C:Documents and Settings%USERNAME%Local SettingsApplication DataGoogleChromeUser DataDefaultHistory
拷贝历史记录文件到桌面:
# 打开命令行cmd,输入以下命令, 自动将History文件复制到桌面, 文件名为History, 没有后缀名
copy "C:Documents and Settings%USERNAME%Local SettingsApplication DataGoogleChromeUser DataDefaultHistory" "C:Documents and Settings%USERNAME%DesktopHistory"
注意说明:%USERNAME% 为你的用户名, 如果执行命令出现错误, 请手动找到该历史记录文件。
Mac OS X
历史记录文件位置:
~/Library/Application Support/Google/Chrome/Default/History
拷贝历史记录文件到桌面:
bash # 打开terminal,输入以下命令, 自动将History文件复制到桌面, 文件名为History, 没有后缀名 cp ~/Library/Application Support/Google/Chrome/Default/History ~/Desktop/History
注意说明:Application Support 中的空格需要转义,所以改为Application Support
Linux/ Unix
历史记录文件位置:~/.config/google-chrome/Default/History
拷贝历史记录文件到桌面:
bash # 打开terminal,输入以下命令, 自动将History文件复制到桌面, 文件名为History, 没有后缀名 cp ~/.config/google-chrome/Default/History ~/Desktop/History
注意说明:如果提示路径不存在, 请自行获取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
补充
完整版源代码存放在github上,有需要的可以下载
https://github.com/shengqiangzhang/examples-of-web-crawlers/tree/master/11.一键分析你的上网行为(web页面可视化) 返回搜狐,查看更多
责任编辑:
python上网行为分析_用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼...相关推荐
- python上网行为分析_转:用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼...
简介 想看看你最近一年都在干嘛?看看你平时上网是在摸鱼还是认真工作?想写年度汇报总结,但是苦于没有数据?现在,它来了. 这是一个能让你了解自己的浏览历史的Chrome浏览历史记录分析程序,当然了,他仅 ...
- 用Python一键分析你的上网行为,看是在认真工作还是摸鱼
2019 AI ProCon"598元学生票"限量抢购中!3日通票团购倒计时6天,扫码查看▲ 作者 | 云外孤岛 出自 | Python那些事(ID:pPythonSomethin ...
- 用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼
简介 想看看你最近一年都在干嘛?看看你平时上网是在摸鱼还是认真工作?想写年度汇报总结,但是苦于没有数据?现在,它来了. 这是一个能让你了解自己的浏览历史的Chrome浏览历史记录分析程序,当然了,他仅 ...
- 用python进行营销分析_用python进行covid 19分析
用python进行营销分析 Python is a highly powerful general purpose programming language which can be easily l ...
- python中成绩分析函数_自学Python笔记:用Python做成绩分析(1)
有朋友会问,刚学了一周,什么是面向对象都还不清楚就可以写程序?还有Python不是写"爬虫"吗? Python是面向对象的语言,函数.模块.数字.字符串都是对象,并且完全支持继承. ...
- anaconda中的python如何进行关联分析_浅析python,PyCharm,Anaconda三者之间的关系
一.它们是什么? Python是一种跨平台的计算机程序设计语言,简单来说,python就是类似于C,Java,C++等,一种编程语言. 2.Anaconda Anaconda指的是一个开源的Pytho ...
- python慢在哪里_求大神分析一下我的python脚本慢在哪里?
请大神们分析下这个python脚本为什么会运行这么慢. 初衷: 公司有个料号系统, 在网站上输入料号就能查询相关的资料, 一般情况下, 我会ctrl+c, 打开网站, ctrl+v, 点击查询, 得到 ...
- python做股票分析_利用Python进行股票投资组合分析(调试)
pythonsp500-robo-advisor-edition Python for Financial Analyses 需要的镜像文件和数据--Robo Advisor edition. 小结 ...
- python图形分析_使用Python图形化分析大Log文件
最近因为项目需要经常分析数据量很大的Log文件,以往靠手工目测的分析方法已不太可能快速分析和定位问题. 由于和我一起做这个项目的同事,会使用Python,编写的Python脚本能够将Log中的相关数据 ...
- python新闻评论分析_使用 python 抓取并分析京东商品评论数据
本篇文章是python爬虫系列的第三篇,介绍如何抓取京东商城商品评论信息,并对这些评论信息进行分析和可视化.下面是要抓取的商品信息,一款女士文胸.这个商品共有红色,黑色和肤色三种颜色, 70B到90D ...
最新文章
- 选IDC房时,用脚本截取丢失包和rtt的值作比对
- 数据库分页存储过程(5)
- Java建造圆判断是否在园内_java – 查找一个圆圈是否在另一个圆圈内
- 学习笔记Hive(九)—— 实例:航空客户价值分析数据预处理
- 内网集群 无法通信_记一次集群内无可用http服务问题排查
- python 键盘输入_跟我一起学python | 探究07
- 农历php,php阳历转农历优化版
- java 反射 镜子,java反射机制 - 巍巍的个人页面 - OSCHINA - 中文开源技术交流社区...
- java spring 事务提交_Spring 事务提交之后再执行操作
- java函数式编程入口_Java中的函数式编程
- Sprite Editor 图集切片精灵
- 极客大学架构师训练营 - 同城快递业务架构设计 - 大作业一
- 娃哈哈的新品,为什么打动不了年轻人?
- MATLAB--求一个矩阵中所有元素的平均值
- Python爬虫-豆瓣电影排行榜TOP250
- 1200PLC学习资料整理
- 解决.bat文件打开是记事本的问题
- 学号20189220余超 2018-2019-2 《密码与安全新技术专题》第七周作业
- ECharts关于y轴刻度调整
- 直方图均衡化算法原理详解
热门文章
- linux动态时钟探索
- error: ‘SA_INTERRUPT’ undeclared (first use in this function)
- 注册(四)之删除绑定
- 用glew,glfw实现的opengl 学习笔记2画一个四方形
- 静默安装apk,静默卸载apk
- 冒泡排序详解(C++)
- excel2019关闭后有残留进程_农药残留检测仪电路设计方案(原理图+PCB+BOM)
- hustoj Runtime Error (运行错误)的解决方法
- 可道云 docker 群晖_【curl】校园网群晖DS120j自动认证
- python 分数等级转换_一文读懂,新高考“3+1+2”模式中等级赋分如何换算?