书签注入:预填充浏览器书签
如何在自动化工作流中以编程方式预填充浏览器书签,打造完整、真实的浏览器身份。
简介
真实的浏览器承载着历史。它有数周乃至数月积累的书签,按文件夹组织,反映着用户的兴趣和习惯。当你为自动化或隐私研究启动一个全新的浏览器实例时,空荡荡的书签栏是将其与真正有使用历史的浏览器区分开来的众多信号之一。书签是更广泛身份层的一部分,使浏览器会话看起来像是被使用过的,而不是刚刚创建的。
BotBrowser 提供了 --bot-bookmarks 标志,可以在启动浏览器实例时预填充书签栏。这使你能够创建从第一次页面加载起就包含真实书签数据的会话。结合其他身份标志如 --bot-cookies 和 --bot-inject-random-history,书签有助于构建一个在所有层面都一致的完整浏览器身份。
隐私影响:为什么书签很重要
追踪系统收集许多信号来构建它们正在交互的浏览器画像。虽然 cookie 和指纹是最常讨论的,但行为和状态信号也发挥着作用。书签的存在与否、浏览历史中的条目数量以及书签栏的状态都有助于浏览器会话的整体画面。
对于隐私研究人员来说,控制书签状态对于可重复的实验很重要。如果你正在测试追踪系统是否对新用户和回访用户有不同的行为,你需要控制浏览器状态的每个方面,包括书签。对于多账户管理,每个身份都受益于与其配置文件其余部分一致的独特书签集:德语配置文件应该有德语书签,开发者配置文件应该有技术书签,以此类推。
空书签栏也是一个实际问题。某些工作流需要与书签相关的 UI 元素交互,或测试网站如何响应 chrome.bookmarks API。预填充书签为这些场景提供了真实的起点。
技术背景
Chromium 如何存储书签
Chromium 将书签存储在用户数据目录中的一个名为 Bookmarks 的 JSON 文件中,具体位于配置文件文件夹下(例如 Default/Bookmarks)。该文件包含一个树形结构,有两个根节点:bookmark_bar(在书签栏上可见)和 other("其他书签"文件夹)。
每个书签条目具有以下属性:
- name/title:在书签栏或管理器中显示的文本
- url:URL 类型书签的目标 URL
- type:
url表示书签,folder表示包含子项的文件夹 - children:嵌套书签和文件夹的数组(用于文件夹类型的条目)
- date_added:表示书签创建时间的时间戳
当浏览器启动时,它读取此文件并填充书签栏和书签管理器。在特权上下文中运行的扩展和 JavaScript 可以通过 chrome.bookmarks API 查询书签。
书签可见性
书签出现在浏览器的多个位置:
- 书签栏:最显眼的位置,启用后显示在地址栏下方
- 书签管理器:通过
chrome://bookmarks访问 - 新标签页:某些配置会显示经常收藏的网站
- 地址栏建议:地址栏在你输入时可能建议已收藏的 URL
通过 --bot-bookmarks 预填充书签可确保它们一致地出现在所有这些位置。
常见方法及其局限性
手动编辑书签文件
你可以创建一个用户数据目录,手动创建或编辑 Bookmarks JSON 文件,然后使用该目录启动浏览器。这可以工作,但有几个缺点:
Bookmarks文件格式包括必须正确的元数据字段(GUID、Chromium 内部格式的 date_added 时间戳)- 你需要明确管理用户数据目录,跟踪哪个目录属于哪个身份
- 目录中的书签数据与其他持久化状态之间没有清晰的分离
使用 chrome.bookmarks API
chrome.bookmarks API 允许以编程方式创建书签,但它仅对浏览器扩展可用,不适用于常规页面 JavaScript 或自动化框架。这意味着你需要安装一个扩展来管理书签,这增加了复杂性并引入了一个可检测的信号(扩展本身)。
框架级别的方法
Playwright 和 Puppeteer 都不提供原生的书签 API。通过这些框架管理书签的唯一内置方式是导航到 chrome://bookmarks 并与 UI 交互,这既慢又脆弱。
BotBrowser 的方案
BotBrowser 通过 --bot-bookmarks 标志在引擎级别处理书签预填充。这种方法避免了上述替代方案的局限性。
引擎级别的填充
当在启动时传递 --bot-bookmarks 时,BotBrowser 在浏览器初始化期间填充书签存储,在任何页面加载和任何浏览器上下文创建之前。书签立即在书签栏、书签管理器和地址栏建议中可用。
JSON 格式
--bot-bookmarks 标志接受描述书签结构的 JSON 字符串:
--bot-bookmarks='[{"title":"Google","type":"url","url":"https://www.google.com"},{"title":"News","type":"folder","children":[{"title":"BBC","type":"url","url":"https://www.bbc.com"},{"title":"Reuters","type":"url","url":"https://www.reuters.com"}]}]'
该结构支持:
- URL 书签:具有
title、type: "url"和url的对象 - 文件夹:具有
title、type: "folder"和包含嵌套书签和文件夹的children数组的对象 - 无限嵌套:文件夹可以包含其他文件夹,层级不限
无需扩展
因为书签填充发生在引擎级别,所以不需要扩展。这消除了书签管理扩展会创建的检测面。
与其他身份信号结合
书签自然地与其他 BotBrowser 身份标志集成。一个完整的身份设置可能包括书签、cookie、浏览历史、时区、区域设置和代理配置,所有这些共同工作以创建一致的浏览器会话。
配置与使用
基本 CLI 使用
# Simple bookmark bar with a few entries
chrome --bot-profile="/path/to/profile.enc" \
--bot-bookmarks='[{"title":"Google","type":"url","url":"https://www.google.com"},{"title":"YouTube","type":"url","url":"https://www.youtube.com"}]'
嵌套文件夹结构
chrome --bot-profile="/path/to/profile.enc" \
--bot-bookmarks='[{"title":"Google","type":"url","url":"https://www.google.com"},{"title":"News","type":"folder","children":[{"title":"BBC","type":"url","url":"https://www.bbc.com"},{"title":"Reuters","type":"url","url":"https://www.reuters.com"}]},{"title":"Shopping","type":"folder","children":[{"title":"Amazon","type":"url","url":"https://www.amazon.com"}]}]'
Puppeteer 集成
const puppeteer = require('puppeteer-core');
const bookmarks = JSON.stringify([
{ title: 'Google', type: 'url', url: 'https://www.google.com' },
{ title: 'YouTube', type: 'url', url: 'https://www.youtube.com' },
{
title: 'News',
type: 'folder',
children: [
{ title: 'BBC', type: 'url', url: 'https://www.bbc.com' },
{ title: 'Reuters', type: 'url', url: 'https://www.reuters.com' },
],
},
]);
(async () => {
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
`--bot-bookmarks=${bookmarks}`,
],
headless: true,
defaultViewport: null,
});
const page = await browser.newPage();
await page.goto('https://example.com');
console.log('Browser launched with pre-populated bookmarks');
await browser.close();
})();
完整身份设置
chrome --bot-profile="/path/to/profile.enc" \
--bot-bookmarks='[{"title":"Google","type":"url","url":"https://www.google.com"},{"title":"Amazon","type":"url","url":"https://www.amazon.de"}]' \
--bot-inject-random-history \
--bot-cookies="@/path/to/cookies.json" \
--bot-config-timezone=Europe/Berlin \
--bot-config-locale=de-DE \
--bot-config-languages=de-DE,de,en \
--proxy-server=socks5://user:pass@de-proxy:1080
验证
使用 --bot-bookmarks 启动后,验证书签是否存在:
const page = await browser.newPage();
// Navigate to bookmark manager
await page.goto('chrome://bookmarks');
// Or check via the chrome.bookmarks API in a privileged context
// Bookmarks should appear in the bookmark bar immediately
你还可以通过在地址栏中输入已收藏 URL 的域名来验证书签是否出现在地址栏建议中。
最佳实践
- 书签与配置文件身份匹配。 德语用户配置文件应该有德语书签,如 google.de、spiegel.de 和 amazon.de。
- 不同身份使用不同书签。 每个浏览器身份应该有独特的书签集以创建不同的配置文件。
- 保持数量真实。 典型用户有 10 到 50 个书签。极大或空的书签集看起来不寻常。
- 包含多种类别。 真实用户会收藏各种网站:搜索引擎、新闻、购物、社交媒体和工作相关的页面。
- 使用文件夹组织。 真实的书签栏通常有"工作"、"购物"或"新闻"等文件夹。包含文件夹增加了真实感。
- 与其他身份标志结合。 书签与
--bot-cookies、--bot-inject-random-history和区域设置/时区配置配合使用效果最佳。
常见问题
--bot-bookmarks 接受什么 JSON 格式?
该标志接受一个书签对象的 JSON 数组。每个对象有一个 title、type("url" 或 "folder"),以及 url(URL 类型)或 children 数组(文件夹类型)。JSON 作为字符串直接在 CLI 参数中传递。
能否从文件加载书签而不是内联 JSON?
--bot-bookmarks 标志直接接受 JSON 字符串。对于大型书签集,在你的自动化脚本中构建 JSON 字符串并作为启动参数传递。
启动后书签何时可用?
书签在浏览器初始化期间填充,在任何页面加载之前。它们立即出现在书签栏和书签管理器中。
书签是否跨会话持久化?
通过 --bot-bookmarks 填充的书签在每次浏览器启动时重新加载。如果你在多个会话中使用相同的 --user-data-dir,会话期间添加的任何书签将持久化在该目录中,但 --bot-bookmarks 总是在其之上应用其条目。
能否将 --bot-bookmarks 与 --bot-inject-random-history 一起使用?
可以。这些标志是互补的。结合使用它们可以创建同时具有书签和浏览历史的浏览器会话,这共同创建了更完整的浏览器身份。
--bot-bookmarks 是否需要特定层级?
--bot-bookmarks 标志在基础 BotBrowser 包中可用,没有层级限制。
应该包含多少书签?
目标是 10 到 50 个书签,匹配典型用户随时间积累的数量。包含常见网站(搜索引擎、电子邮件、社交媒体)和与配置文件角色匹配的小众网站的组合。
总结
使用 --bot-bookmarks 预填充书签为 BotBrowser 会话添加了一个真实的身份层。结合 cookie、浏览历史和一致的区域设置,书签有助于创建反映真实使用模式而非全新安装的浏览器配置文件。
有关相关主题,请参阅 Cookie 管理 了解会话持久化,合成浏览历史 了解历史填充,以及 配置文件管理 了解完整身份集的组织。