用 Python 分析你的上网习惯!

本文介绍如何使用Python分析PC端Chrome和Firefox的浏览历史。通过sqlite数据库,提取并理解History和Places.sqlite文件,利用SQL查询操作获取详细信息。内容包括SQL基础知识、查询技巧以及数据导出,帮助你了解浏览器数据背后的上网习惯。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(当然本文仅针对 PC 浏览器)

安卓用户也不是不可以,但是手机浏览器的门类实在太多,难以一个个研究。所以本文仅采用 PC 端的 Chrome 和 Firefox 浏览器作为示例。同时,由于本文在 Linux 系统环境下写作,有可能与 Windows 系统下的操作有所出入。

 

至于手机浏览历史记录,应该可以用同步或者导出的方式进行。

 

提取历史记录的保存文件

 

Chrome 浏览器可以在地址栏输入:chrome://version/

 

 

Firefox 浏览器可以在地址栏输入:about:profiles

 

 

其他种类浏览器( 360 安全浏览器、搜狗高速浏览器、QQ 浏览器、百度浏览器之流)应该不会差别很大,本人未曾验证,还请各位看官自行解决。

 

其中 Chrome 浏览器保存历史数据的文件是 History,没有扩展名。但实际上就是 sqlite 的数据库文件;而 Firefox 浏览器对应存放数据的文件是 Places.sqlite,这个文件实际上存放的信息包括历史记录、书签、设置及附加组件,同样也是 sqlite 的数据库文件。

 

关于 Sqlite

 

SQLStructured Query Language:结构化查询语言)是一种特定目的程式语言,用于管理关系数据库管理系统(RDBMS),或在关系流数据管理系统(RDSMS)中进行流处理。[1]

 

简单来说,就是用于管理数据库的专用的语言。除了以 SQL 语句为代表的数据库工具,同时也有以 NoSql 为代表的非关系型的数据库,例如 MongoDB。其主要特点是不使用 SQL 查询语句。

 

当然本文仅仅只是着重于一点点 Sqlite3 的使用,因为这对于在本文要做的事情是有帮助的。

 

通常而言 Linux 系统的发行版往往自带 Sqlite3,只需要在终端输入 sqlite3 并在其后加上数据库文件名作为参数,即可进行此数据库的查询操作了。但在这之前可能还需要一点点准备知识。

 

首先,SQL 数据库通常是由几张表格组成,每一张表格之间都存在着关系。每一张表格都有表头(Headers),也就是普通 Excel 表格上的标题,也叫字段。通常这代表了一列数据的主要特征。其他次要特征包括:数据类型(Type)、是否是主键(Primary Key)、是否可以为空值(Null)、默认值(Default)、布尔值(BOOLEAN)

 

进入数据库文件后,.table 命令可以查看所有的表格。(注意该命令前有一个点)

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
$ sqlite3 HistorySQLite version 3.23.1 2018-04-10 17:39:29Enter ".help" for usage hints.sqlite> .tabledownloads                meta                     urls                   downloads_slices         segment_usage            visit_source           downloads_url_chains     segments                 visits                 keyword_search_terms     typed_url_sync_metadata

pragma table_info([table_name]); 命令可以查询相应表格的所有的表头。(注意这个命令前没有点,且结尾处需要加上分号,或者换行之后再加上分号,用于表示命令结束。)

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
sqlite> pragma table_info(visits);0|id|INTEGER|0||11|url|INTEGER|1||02|visit_time|INTEGER|1||03|from_visit|INTEGER|0||04|transition|INTEGER|1|0|05|segment_id|INTEGER|0||06|visit_duration|INTEGER|1|0|07|incremented_omnibox_typed_score|BOOLEAN|1|FALSE|0

.dump 命令可以显示一个表格的所有信息,不过不易于阅读。所以使用 Select 查询语句更容易阅读表格的信息。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
sqlite> .dump visitsPRAGMA foreign_keys=OFF;BEGIN TRANSACTION;CREATE TABLE visits(id INTEGER PRIMARY KEY,url INTEGER NOT NULL,visit_time INTEGER NOT NULL,from_visit INTEGER,transition INTEGER DEFAULT 0 NOT NULL,segment_id INTEGER,visit_duration INTEGER DEFAULT 0 NOT NULL,incremented_omnibox_typed_score BOOLEAN DEFAULT FALSE NOT NULL);INSERT INTO visits VALUES(16093,9299,13202840367496968,0,805306368,0,0,0);INSERT INTO visits VALUES(16094,9299,13202840480577849,0,805306368,0,0,0);INSERT INTO visits VALUES(16095,9302,13202840482160798,0,268435456,0,0,0);INSERT INTO visits VALUES(16096,9303,13202840482160798,16095,2684354560,0,353266479,0);INSERT INTO visits VALUES(16097,9299,13202840816848619,0,805306368,0,0,0);...INSERT INTO visits VALUES(22432,12966,13210610317809993,22431,805306368,212,0,0);INSERT INTO visits VALUES(22433,12969,13210610329001790,0,268435460,0,0,0);INSERT INTO visits VALUES(22434,12968,13210610329001790,22433,2684354564,0,0,0);INSERT INTO visits VALUES(22435,13220,13210613943693189,0,805306368,0,0,0);INSERT INTO visits VALUES(22436,12966,13210616113132979,22431,805306376,212,0,0);INSERT INTO visits VALUES(22437,13220,13210616470103600,0,805306368,0,0,0);CREATE INDEX visits_url_index ON visits (url);CREATE INDEX visits_from_index ON visits (from_visit);CREATE INDEX visits_time_index ON visits (visit_time);COMMIT;

Select 的做法:(注意语句结束的分号,因为 Select 语句可以写成多行,所以需要使用分号作为休止符)

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
sqlite> select * from visits;16093|9299|13202840367496968|0|805306368|0|0|016094|9299|13202840480577849|0|805306368|0|0|016095|9302|13202840482160798|0|268435456|0|0|016096|9303|13202840482160798|16095|2684354560|0|353266479|016097|9299|13202840816848619|0|805306368|0|0|016098|9299|13202840831139916|0|805306368|0|882287|0...22436|12966|13210616113132979|22431|805306376|212|0|022437|13220|13210616470103600|0|805306368|0|0|0

当然我们的视觉系统仍然无法接受这种杂乱的堆砌表格。所以我们还可以使用 .mode column。这一命令是把原先的 list 显示模式改为 column (行),就是在终端中实现列对齐。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
sqlite> .mode columnsqlite> select * from visits;16093       9299        13202840367496968  0           805306368   0           0               0                              16094       9299        13202840480577849  0           805306368   0           0               0                              16095       9302        13202840482160798  0           268435456   0           0               0                              16096       9303        13202840482160798  16095       2684354560  0           353266479       0                              16097       9299        13202840816848619  0           805306368   0           0               0                              16098       9299        13202840831139916  0           805306368   0           882287          0                         16099       9304        13202878582356542  0           268435461   0           0               0...22437       13220       13210616470103600  0           805306368   0           0               0

不过,如果显示器的不够宽,或者终端的窗口不够大,会造成表格的折叠。一样只会挑战人类的视觉承受极限。另外,表格中过长的内容在 column 模式下不予显示超出的部分,不过可以手动调节每一个格子的宽度。

 

但是这样做的表格观感还是缺了一个常见的东西,就是表格的标题。所以还需要使用 .header on 命令是的查询结果显示出表头。

 

关于当前表格的显示状态,可以用 .show 命令查看。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
sqlite> .showecho: offeqp: offexplain: autoheaders: onmode: columnnullvalue: ""output: stdoutcolseparator: "|"rowseparator: "\n"stats: offwidth:     filename: History

其中 colseparator 也就是行分隔符,是 "|" 。这样的话,导出的文件也是用竖线作为分隔符。但是 csv 文件的标准格式中,是用 "," 作为行分割符。那么如果需要导出成 csv 文件需要更改行分隔符。具体命令如下:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
sqlite> .separator ","sqlite> .mode listsqlite> select * from visits;id,url,visit_time,from_visit,transition,segment_id,visit_duration,incremented_omnibox_typed_score16093,9299,13202840367496968,0,805306368,0,0,016094,9299,13202840480577849,0,805306368,0,0,016095,9302,13202840482160798,0,268435456,0,0,016096,9303,13202840482160798,16095,2684354560,0,353266479,016097,9299,13202840816848619,0,805306368,0,0,0...22437,13220,13210616470103600,0,805306368,0,0,0

接下来是查询结果的导出到文件的操作。这里要用到 output 命令。

  •  
  •  
  •  
sqlite> .output file_name.csvsqlite> select * from visits;sqlite> .output stdout

以下是使用表格软件打开对应 csv 文件的显示效果。

 

实际而言,output 命令是把 output file_name 和 output stdout 之间的原本在终端显示的内容直接作为文本写入到文件中去了。

 

Select 查询

 

如果你观察的足够仔细的话,你会发现,visits 这个表格并没有任何的网址。实际上其中的 url 使用的是网址的编号,而其后还记录了访问时间。而 url 编号和 url 地址存放于 urls 这个表格中。

 

所以如果要准确得到每一个网址和其对应的访问时间,就必须使用 visits 和 urls 两个表格。而这在数据库的操作一般是内连接

 

  •  
sqlite> select urls.url, title, visit_time from urls inner join visits on urls.id = visits.url;

同样应用之前的文件导出操作即可生成一张包含网址、网址标题、访问时间的完整的表格。

 

Firefox 浏览器的操作大体一致。其中的 moz_historyvisits 相当于 visits,moz_places 相当于 urls 。而 select 语句可以写成:

  •  
  •  
  •  
sqlite> select url, title, visit_date   ...> from moz_places inner join moz_historyvisits   ...> on moz_places.id = moz_historyvisits.place_id;

不过在 Firefox 浏览器的里的 moz_places 表格中还存在着一个 rev_host,也就是反序域名。虽然不理解反序有什么用,但 Firefox 已经把所有的域名都提取出来了。

 

另外,Linux 系统或者 Mac OS 不带 Sqlite3 可自行检索安装方法;Windows 系统有命令行操作版本,同时也有带 GUI 的版本。GUI 版本笔者未曾深入了解,故无相应示例操作;命令行的版本操作上应该与本文不会有较大差别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值