将Python专栏设为星标 福利大奖不错过
作者:云外孤鸟
/cloudbird/p/11336663.html
简介
想看看你最近一年都在干嘛?看看你平时上网是在摸鱼还是认真工作?想写年度汇报总结,但是苦于没有数据?现在,它来了。
这是一个能让你了解自己的浏览历史的Chrome浏览历史记录分析程序,当然了,他仅适用于Chrome浏览器或者以Chrome为内核的浏览器。
在该页面中你将可以查看有关自己在过去的时间里所访问浏览的域名、URL以及忙碌天数的前十排名以及相关的数据图表。
代码思路
1. 目录结构
首先,我们先看一下整体目录结构
Code├─ app_callback.py回调函数,实现后台功能├─ app_configuration.py web服务器配置├─ app_layout.py web前端页面配置├─ app_plot.pyweb图表绘制├─ app.pyweb服务器的启动├─ assetsweb所需的一些静态资源文件│ ├─ cssweb前端元素布局文件│ │ ├─ 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..pyweb前端页面配置,包含html, css元素。
app_plot.py这个主要是为实现一些web前端的图表数据。
app.pyweb服务器的启动。
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_sortexcept:# 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]# 简化urlkey = url_simplification(url)if (key in dict_data.keys()):dict_data[key] += 1else: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 figureelse:# 取消更新页面数据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_dataelse:# 没找到date_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))print('新接收到一条客户端的数据, 数据错误, 时间:{}'.format(date_time))return Nonereturn None
该函数的代码流程为:
首先判断用户上传的数据contents
是否不为空,接着将客户端上传的文件进行base64解码。并且,为客户端上传的文件添加后缀,防止文件重复覆盖,最终将客户端上传的文件写入本地磁盘文件。
写入完毕后,使用sqlite读取本地磁盘文件,若读取正确,则返回解析后的数据,否则返回None
接下来,就是我们数据提取最核心的部分了,即从Chrome历史记录文件中提取出我们想要的数据。由于Chrome历史记录文件是一个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_sortexcept:# 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
。
返回一个排序好的数据
这里我们列出每个字段代表的意思:
6. 如何获取Chrome历史记录文件
Windows Vista, Windows 7, Windows 8, Windows 10
历史记录文件位置:
C:\Users\%USERNAME%\AppData\Local\Google\Chrome\User Data\Default\History
拷贝历史记录文件到桌面:bash # 打开命令行cmd,输入以下命令, 自动将History文件复制到桌面, 文件名为History, 没有后缀名 copy "C:\Users\%USERNAME%\AppData\Local\Google\Chrome\User Data\Default\History" "C:\Users\%USERNAME%\Desktop\History"
注意说明:%USERNAME%
为你的用户名, 如果执行命令出现错误, 请手动找到该历史记录文件。
Windows XP
历史记录文件位置:
C:\Documents and Settings\%USERNAME%\Local Settings\Application Data\Google\Chrome\User Data\Default\History
拷贝历史记录文件到桌面:
# 打开命令行cmd,输入以下命令, 自动将History文件复制到桌面, 文件名为History, 没有后缀名copy "C:\Documents and Settings\%USERNAME%\Local Settings\Application Data\Google\Chrome\User Data\Default\History" "C:\Documents and Settings\%USERNAME%\Desktop\History"
注意说明:%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上,有需要的可以下载
/shengqiangzhang/examples-of-web-crawlers/tree/master/11.一键分析你的上网行为(web页面可视化)
项目持续更新,欢迎您star本项目
关注公众号「Python专栏」,后台回复:机器学习电子书,就可以获取100本免费电子书哦~
[ 完 ]
今日赠送书籍
从深度学习框架到开发理念的跃迁
复制淘口令“¥wiQvY9ch8Mg¥”了解更多
本书简介
恭喜财才材ccc读者深得我心,各赠送书籍一本。
请财才材ccc同学联系小胖:moonhmily1
今日留言主题
你上网都干嘛呢
·合作、交流请关注微信公号Python专栏(ID:xpchuiit),转载请添加微信moonhmily1
延伸阅读
Python
23个Python爬虫开源项目代码:微信、淘宝、豆瓣、知乎、微博等。我要做马来人
一篇文章看懂大数据分析就业前景及职能定位
给急着找工作的人一些建议,别在被骗了!
格局
小胖亲测,分享3个实用建议,帮助你提升工作效率
创业半年总结出的这3点,老板看了也点赞
和出租车司机聊天:如果你觉得生活就这样了,那谁也救不了你
思维升级 | 25W运营一年色拉店,你能赚几万?
喜欢就在看吧