xero/w3b.cam
GitHub: xero/w3b.cam
基于 Shodan API 和手动来源的公开网络摄像头聚合数据库,可将采集到的摄像头数据烘焙为可浏览的分页静态画廊网站。
Stars: 0 | Forks: 0
# Shodan 网络摄像头可视化工具
## 要求
- [Bun](https://bun.com) 1.3 或更高版本。
- 拥有包含 API key 的 Shodan 账户。不需要付费会员,但免费层级提供的查询额度非常少。
- 将你的 API key 导出为 `SHODANTOKEN` 环境变量。
```
export SHODANTOKEN=your_api_key_here
```
要导入 YouTube 直播流,你还需要一个 YouTube Data API v3 key,并将其导出为 `YOUTUBE_API_KEY`。它仅读取公开的视频元数据;API key 无法修改频道(这需要 OAuth,而本项目从不使用 OAuth)。如果你只使用 Shodan 来源,则可以跳过此项。
```
export YOUTUBE_API_KEY=your_api_key_here
```
## 设置
```
bun install
```
这将安装 `shodan-ts`(API 客户端)和 Bun 的类型定义。SQLite 已内置于 Bun 中,因此无需添加其他任何内容。
随时运行 `bun typecheck` 以使用 `tsc --noEmit` 对源码进行类型检查。
## 获取数据库
数据库不在代码仓库中。`camhunting.sqlite` 大小高达数百 MB 并且只会不断增大,因此它作为名为 `db-store` 的公开预发布(prerelease)资产存在,而不是放在 git 中。你有两种获取方式:拉取在线网站构建所用的已发布副本,或者从一个空数据库重新开始。
**拉取已发布的数据库。** 这是网站正在提供服务的确切数据库,可直接用于浏览和编辑。
```
bun sync --pull
```
它从 `db-store` release 下载 `camhunting.sqlite`,覆盖你的本地副本,并删除过期的 `-wal` 和 `-shm` 伴随文件,以便 SQLite 能干净地读取新文件。代码仓库是公开的,因此任何 GitHub 账户都可以使用,你不需要成为协作者。同步操作由 `gh` CLI 驱动,因此请先安装并通过 `gh auth login` 进行身份验证。有关完整的编辑流程,请参见[本地编辑](#editing-locally)。
**不使用 `gh` 下载。** 该 release 是公开的,因此你可以直接通过 HTTPS 获取资产,无需 CLI 且无需登录。之后你需要自行删除伴随文件,因为普通的下载过程会跳过该步骤。
```
curl -L -o camhunting.sqlite \
https://github.com/xero/w3b.cam/releases/download/db-store/camhunting.sqlite
rm -f camhunting.sqlite-wal camhunting.sqlite-shm
```
**改为重新开始。** 要从已播种的空数据库而非已发布数据构建你自己的数据库,请运行 `bun initdb`,并使用 `bun scrape` 或 `bun import` 填充数据。
## 用法
核心流水线包含四个命令。摄像头来自 Shodan API(`scrape`)或 `import`,后者是一条根据类型标签提取所有非抓取源的命令:`--shodan` 用于你已有的原始 JSON 文件,`--youtube` 用于精选的直播流列表,`--mjpeg` 用于手动搜寻的摄像头列表。每个来源都写入同一个数据库,`bake` 将其转换为静态网站,而 `serve` 用于在本地托管该网站。
**`bun scrape [--pages N]`。** 获取 `N` 个搜索页面(默认为 1,每页 100 个结果)并将新摄像头保存到 `camhunting.sqlite`。重复运行是安全的;已存储的摄像头将被跳过。每页消耗 1 个查询额度。
**`bun import --shodan [dir]`。** 从目录(默认为 `./in`)将原始 Shodan JSON 文件加载到数据库中。它会读取找到的每一个 `.json` 文件,不使用 API 且不消耗额度,并发出警告以跳过无法解析的文件,且仅存储带有截图的摄像头。接受主机查询、搜索结果和单个 banner。相同的命令通过 `--youtube` 和 `--mjpeg` 还可以提取另外两种来源的数据,这将在下文介绍。
**`bun bake`。** 读取数据库并将分页的静态网站写入 `out/`。它按 IP 将行分组为每个主机一个条目,将每张截图提取到 `out/img/` 下的文件中,并生成一个每页 8 个主机的分页索引,以及每个主机的独立页面。`out/` 目录在每次运行时都会被擦除并重建。不消耗任何内容且不调用任何 API。
**`bun serve`。** 通过 HTTP 在 `http://localhost:1337` 托管 `out/`。该网站需要服务器,因为其 htmx 导航需要获取页面片段,而浏览器会阻止通过 `file://` 发出的这些请求。使用 `PORT=3000 bun serve` 覆盖端口。
```
bun scrape --pages 5
bun bake
bun serve
```
然后打开 `http://localhost:1337`。
你可以使用 `--query "your query"` 覆盖搜索查询。默认值为:
```
has_screenshot:1 screenshot.label:webcam -screenshot.label:desktop
```
这会匹配具有标记为网络摄像头截图的主机,并排除桌面捕获。
### YouTube 直播流
**`bun import --youtube [--limit N]`。** 读取位于 `in/youtube.md` 的本地列表(每行一个 `title `,可混合使用 `watch?v=`、`youtu.be/` 和 `youtube.com/live/` 形式),该列表与导入器读取的 `in/` 目录在同一个位置。`in/` 和 `out/` 均已被 gitignore 忽略,因此此列表会保留在你的机器上。从 YouTube Data API 获取每个视频的元数据和缩略图,并将它们以 `kind='stream'` 的形式更新/插入(upsert)到统一的 `cams` 表中,以视频 ID 作为键。重新运行会刷新现有流并获取更新的直播缩略图,而不是重复创建。`--limit N` 仅处理前 N 个唯一条目,用于快速测试。需要 `YOUTUBE_API_KEY`。
**`bun import --youtube --url [--label "Title"]`。** 通过 URL 添加或刷新单个流,而无需修改文件。这就是 `youtube` CI 工作流一次提取一个流的方式,因为批量列表并未提交。`--label` 设置显示标题;省略它则回退到视频自身的标题。
流在 `/streams` 有自己的画廊,可从页眉导航访问。`bake` 将每个流渲染为独立的卡片,并且每个流的详情页面会链接到来自同一频道的其他流。
```
export YOUTUBE_API_KEY=your_api_key_here
bun import --youtube
bun bake
bun serve
```
### MJPEG 摄像头搜寻 cams
**`bun import --mjpeg [file] [--limit N] [--concurrency N]`。** 读取精选的 MJPEG 摄像头 URL 列表(每行一个,默认为 `in/mjpeg.md`)。空行和 `#` 注释会被跳过,URL 前面可选的 `label` 会被保留。与 `in/youtube.md` 一样,该列表被 gitignore 忽略并保留在你的机器上,因此你可以随着搜寻更多摄像头不断向其追加并重新运行。根据 [tips.md](./tips.md) 中的指纹按供应商对每个 URL 进行分类,使用 ffmpeg 为画廊卡片烘焙静态图像,并将该摄像头以 `kind='feed'` 的形式更新/插入到统一的 `cams` 表中。重新运行会刷新缩略图,而不是重复创建摄像头。`--limit N` 仅提取前 N 个唯一的摄像头;`--concurrency N` 设置快照的并发数,默认为 24。
该网站通过 https 提供服务,因此摄像头的播放方式取决于其 feed。https 流可作为平滑的 Motion JPEG `
` 实时嵌入;https 快照会自动刷新;由于浏览器会阻止混合内容,http feed 无法嵌入,因此它会显示烘焙的静态图像以及在新标签页中打开该 feed 的“查看直播”链接。查看器页面的 URL(例如 Mobotix 的 `guestimage.html`、Panasonic 的 `CgiStart` 和 Axis 的 `#view`)会被解析为其真实的流或快照 endpoint,因此它们仍然可以获取缩略图。这些摄像头加入位于 `/feeds` 的 feed 画廊,并按供应商进行标记。
```
bun import --mjpeg
bun bake
bun serve
```
## 本地编辑
整理数据(将主机列入黑名单、固定其卡片图片或为其添加标签)曾经意味着需要从 Actions 标签页运行工作流,从而直接编辑已发布的数据库。现在你可以在自己的机器上针对本地副本完成所有这些操作,在浏览器中预览结果,并且只有在满意时才发布。该循环包含三个命令。
```
bun sync --pull # copy the published database down, overwriting your local one
bun dev # serve it locally and edit by right-clicking
bun sync --push # publish your edits and rebuild the live site
```
**`bun sync --pull`。** 从 `db-store` release 下载 `camhunting.sqlite` 并覆盖你的本地副本,因此你完全可以从网站当前提供的内容开始。它随后会删除过期的 `-wal` 和 `-shm` 伴随文件,以便 SQLite 能干净地读取新文件。
**`bun dev`。** 烘焙网站的开发版本,在 `http://localhost:1337` 提供服务,并打开你的浏览器。右键单击摄像头卡片或截图可将主机列入黑名单、将该端口固定为卡片图片或附加标签;右键单击流或 feed 卡片或其详情页面,也可以为其添加标签。Tag 菜单以标签(chips)的形式列出实体当前的标签,每个标签都有一个 × 用于删除,因此你可以在一个地方进行添加和删除。每个操作都会直接写入本地数据库。更改会立即应用在页面中,无需重新构建,因为从几百 MB 的数据库中重新提取数千张截图需要几十秒的时间。当你想要重新生成静态 `out/` 时,请运行 `bun bake`。它从不会在 CI 中运行,也从不会触及已发布的数据库。
**`bun sync --push`。** 将你的本地数据库作为 `db-store` 资产上传,并触发 `build` 工作流,以便在线网站根据你的编辑进行重建。如果尚不存在,它会在首次推送时创建 `db-store` release。
双向都会覆盖整个数据库,因此每个方向都会打印出两个副本的大小和时间戳比较,并要求你确认。当你要覆盖的副本比要替换它的副本更新时,它会向你发出警告,因为定时抓取工具每六小时刷新一次已发布的数据库,而过期的本地推送可能会破坏更新的数据。传递 `--yes` 可跳过提示。同步由 `gh` CLI 驱动,因此你需要安装并进行身份验证。
**`bun sync --merge`。** 拉取已发布的数据库,并一步将其新摄像头合并到你本地的副本中,适用于本地副本包含尚未推送的编辑的情况。定时抓取工具每六小时向存储中添加一次摄像头,而纯粹的 `--pull` 仅为了获取它们就会破坏你未推送的工作。它将你当前的数据库备份为带有时间戳的 `camhunting.sqlite-.bak`,将存储内容下载到临时文件中,将存储中的新行合并到本地数据库的副本中,然后将该副本替换为活动的数据库。你的数据库从不会就地覆盖;它只会在合并成功后被替换,因此中断的运行会保持原始文件不变。它无人值守运行,没有提示。备份会被保留;一旦对结果满意,请自行将其删除。
**`bun merge `。** `--merge` 运行的合并操作,在你已经有两个并排的数据库时单独公开。它将源数据库中的新摄像头折叠(合并)到目标数据库中,而不是覆盖任何一个:
```
bun merge camhunting.sqlite.prod camhunting.sqlite
```
它通过 `(ip_str, port)` 对比源和目标的 `cams` 表(即 `kind='cam'` 行),并且仅插入目标中缺失的摄像头,完全原样复制,包括每个摄像头最初的 `first_seen` 和任何固定项(pin)。目标中已有的行保持不变,因此你自己的固定项、标签和整理操作都能保留。只写入目标数据库;源数据库以只读方式打开。传递 `--dry-run` 可预览差异而不写入任何内容,或传递 `--yes` 跳过确认提示。
## 工作原理
抓取工具对搜索结果进行分页,并以 IP 和 port 为键,为每个摄像头服务存储一行。由于该对是主键,因此第二次运行仅插入以前未见过的摄像头。每一行都保留位置、网络所有者、base64 格式的截图,以及完整的原始 JSON 匹配项以供将来使用。
一些值得了解的细节:
- **截图需要 `minify: false`。** Shodan 默认会截断大字段,这会导致截图丢失。客户端始终请求完整记录。
- **请求的频率限制为大约每秒一次。** `shodan-ts` 不进行节流,也不重试速率限制错误,因此抓取工具会拉开调用间隔,并在收到 `429` 和 `5xx` 响应时退避。
- **RDP 和 VNC 屏幕已被过滤。** 某些主机提供 Shodan 标记为网络摄像头的远程桌面或 VNC 登录界面。抓取工具和导入器在提取时会跳过任何 `remote desktop protocol` 或 `vnc` 产品。该防护仅阻止新行,因此 `bun purge` 会追溯性地删除在其之前存在的任何此类行。之后重新运行 `bun bake`。
- **移除的主机将保持移除状态。** `bun blacklist ` 会删除每个匹配的行,并将该条目记录在黑名单表中;抓取工具和导入器会跳过列出的任何内容,因此你删除的主从不会在以后的运行中再次出现。IP 完全匹配(每个端口);主机名或域名匹配自身以及任何子域名,因此 `bun blacklist cloudzy.com` 也会删除 `cam.node.cloudzy.com`。IP 位于 `blacklist` 表中,主机名位于 `host_blacklist` 表中。使用 `bun unblacklist ` 撤销任一操作,然后重新运行 `bun scrape` 再次获取该主机。全新的数据库以内置的黑名单主机名列表开始;IP 一栏初始为空。
- **你可以挑选主机的卡片图片。** 在多个端口上出现的主机拥有多张截图,并且其画廊卡片默认显示最新的一张。`bun reorder ` 固定一个端口,以便其截图优先显示,而 `bun reorder --clear` 恢复为默认设置。固定项保存在 `preferred` 列中,抓取工具和导入器从不会覆盖它,因此它能在以后的运行中保留下来。重新运行 `bun bake` 以重建网站。
- **标签在所有三种来源中是统一的。** `bun tag ` 将自由格式的标签附加到摄像头(通过 IP)、流(通过视频 ID)或 feed 摄像头(通过 ID),存储在 `meta` 表(`type='tag'`)中,以 `(kind, ref, type, value)` 为键。相同的标签跨越所有来源,因此在网络摄像头、流和 feed 摄像头上标记 `street` 会将这三种来源全部分组在该标签下。标签被规范化为小写并去重,一个实体可以携带多个标签。它们显示在每个详情页面上,在页眉导航的 `/tags` 处构成标签云,并且每个标签都链接到 `/tags/` 的分页浏览页面,其中混合了携带该标签的每个实体。使用 `bun untag ` 删除一个标签,或者在 `bun dev` 中通过右键单击 Tag 菜单中标签上的 × 来删除。重新运行 `bun bake` 以重建网站。
- **YouTube 流存在于它们自己的表中。** `bun import --youtube` 读取 `in/youtube.md`,从 YouTube Data API 中提取每个视频的元数据和缩略图,并将它们以 `kind='stream'` 的形式存储在统一的 `cams` 表中,并以视频 ID 为键。缩略图即为截图;YouTube 会保持 24/7 实时摄像头的缩略图是最新的,因此重新运行会刷新它。它们在 `/streams` 渲染为扁平的画廊,每个流一张卡片,并且每个流的页面都会链接到共享其频道的其他流。
- **MJPEG 摄像头来自精选的 URL 列表。** `bun import --mjpeg` 读取 `in/mjpeg.md`(每行一个摄像头 URL),并使用 [tips.md](./tips.md) 中的 endpoint 指纹按供应商对每个摄像头进行分类。它使用 ffmpeg 为卡片烘焙静态图像,并以 `kind='feed'` 的形式更新/插入到统一的 `cams` 表中,通过特定供应商的 `source` 进行区分。由于网站是 https,因此只有 https feed 可以实时嵌入,流为平滑的 Motion JPEG `
`,快照为自动刷新的 `
`;http feed 受到混合内容阻止,因此它们被存储为 `link` 类型,显示烘焙的静态图像以及“查看直播”链接。查看器页面 URL 会解析为其真实的媒体 endpoint,因此它们仍然可以生成缩略图。重新运行 `bun bake` 以重建网站。
- **主页是精选的混合内容。** `index.html` 是着陆页,而不是索引的第一页:它显示一行摄像头和一行流,每行最多包含两张精选卡片,其次是该类型的最新内容。`bun feature ` 向 `meta` 表添加一个以 `(kind, ref)` 为键的条目(`type='featured'`,摄像头的 IP,流为视频 ID)。该集合是无界的,每次构建都会随机挑选每种类型两张进行展示,因此主页会自行轮换。其行已消失的精选条目会被跳过,并从最新内容中补充,因此页面始终填满四个和四个。使用 `bun unfeature ` 删除一个条目,或者在 `bun dev` 中通过右键单击卡片并选择取消精选(Unfeature)来实现。完整的分页画廊位于 `/hosts` 和 `/streams`,可从页眉导航访问,旁边还有包含所有类型的组合画廊 `/gallery`。重新运行 `bun bake` 以重建网站。
- **可视化工具会转义所有内容。** Banner 文本(例如组织名称和主机名)来自扫描的主机,并且是不可信的,因此每个值在到达页面之前都会进行 HTML 转义。主机文件夹名称保留点分 IP,但会通过十六进制和点的白名单,而 feed 文件夹名称通过 `[A-Za-z0-9_.-]` 白名单,因此恶意值无法转义到输出目录之外。YouTube 标题和频道名称以相同的方式转义,并且视频 ID 别名(slug)被列入 `[A-Za-z0-9_-]` 白名单。
- **每个具有地理位置的摄像头都会绘制在世界地图上。** `/map` 位于页眉导航中,是一个烘焙的 SVG,它将所有三种来源中每个已定位的摄像头绘制为链接到其详情页面的点。Shodan 和 feed 摄像头已携带坐标;YouTube 不发布坐标,因此 `bun geo ` 手动分配坐标,并内联存储在流的 `cams` 行上。在开启 JavaScript 的情况下,你可以拖动平移并滚动缩放;如果不开启,地图是一个固定的世界视图,其点仍然是普通链接,每个点都有一个位置提示。重新运行 `bun bake` 以重建网站。
- **该网站无需 JavaScript 也能工作。** 每个索引页面和每个主机对应的页面都是带有普通链接的真实文件,因此它可以自行保持可浏览状态。当开启 JavaScript 时,htmx 会拦截这些链接并仅交换页面主体,从而跳过外壳和共享资产的重载。每个页面都以两种形式从单个源字符串生成,即完整文档和仅包含主体的代码片段,因此两者不会产生差异。
## 查询额度
## 项目布局
```
src/
initdb.ts create and seed an empty database
config.ts query and tuning constants
types.ts screenshot, match, and row interfaces
util.ts escaping, screenshot extraction, row mapping
shodan.ts client factory and retry/backoff wrapper
yt-api.ts YouTube Data API client, youtube.md parser, thumbnail fetch
db.ts schema, open/close, and inserts
scraper.ts fetch cameras from the Shodan API, dedupe, store
import.ts unified importer CLI: --shodan | --youtube | --mjpeg
ingest.ts shared ingest core (bulk + single-record), CLI and web
shodan-source.ts normalize and filter raw Shodan JSON banners into rows
mjpeg-source.ts classify an MJPEG cam URL by vendor (see tips.md)
osiris-source.ts classify + snapshot Osiris cams; shared feed row builder
osiris.ts internal: re-ingest the one-off Osiris dump into feed
blacklist.ts drop a host and record it so scrapes skip it
unblacklist.ts reverse a blacklist entry
reorder.ts pin a host's card image to one port
tag.ts attach a free-form label to a cam, stream, or feed cam
untag.ts remove a tag from a cam, stream, or feed cam
feature.ts add a cam or stream to the homepage featured set
unfeature.ts remove a cam or stream from the featured set
geo.ts assign a YouTube stream's map coordinates (cams.lat/lng)
purge.ts remove stored RDP/VNC rows that predate the ingest filter
render.ts pure HTML rendering (grouping, pager, pages, shell)
worldmap.ts pre-projected world-country outlines for the map page
build.ts database to static site (orchestrator)
serve.ts static file server for out/
dev.ts local dev server with right-click blacklist/reorder/tag
dev-client/ browser editing UI (js and css), served from source
sync.ts pull, push, or merge the database with the db-store release
merge.ts merge new webcam rows from one database into another
in/ curated inputs (gitignored)
youtube.md YouTube live-stream list, source for `bun import --youtube`
mjpeg.md MJPEG camera URL list, source for `bun import --mjpeg`
*.json raw Shodan JSON for `bun import --shodan`
new/osiris-cameras.json Osiris dump, source for the internal `bun run osiris`
camhunting.sqlite generated database (gitignored)
out/ generated site (gitignored). Clean folder URLs: every page is a
folder holding index.html, with a co-located index.snippet.html for
htmx swaps. Bare landings (/hosts) mirror page 1 (/hosts/1).
index.html curated homepage (featured + newest cams and streams)
gallery/{n}/ all-kinds gallery, newest-discovered first
hosts/{n}/ paginated cams gallery
hosts// one page per host (dotted IPv4, e.g. hosts/194.94.76.131)
streams/{n}/ paginated YouTube streams gallery
streams/yt-/ one page per YouTube stream
feeds/{n}/ paginated feeds gallery
feeds// one page per feed (mjpeg- reads as feeds/)
fingerprints/ make/model/count breakdown, each make linking its vendor gallery
fingerprints//{n}/ per-vendor gallery of matching cams
tags/ tag cloud, links to per-tag browse pages
tags//{n}/ one paginated browse page per tag
map/ world map of every geolocated camera
tips/ cam-hunting guide (baked from tips.md)
img/ extracted screenshots and thumbnails
htmx.min.js vendored htmx library
```
## GitHub Actions
`.github/workflows/` 中的工作流在 CI 中运行相同的命令。该网站可自行构建并部署到 GitHub Pages,抓取工具按计划运行,而添加 YouTube 流以及黑名单、重新排序、添加标签、取消标签、精选、取消精选和地理位置编辑操作都可以从 Actions 标签页进行,无需本地签出。
**`build`。** 将数据库烘焙到 `out/` 并将其部署到 GitHub Pages。它是可重用的,因此其他工作流在更改数据后会调用它。单独运行它以在不进行抓取的情况下重新部署。
**`scrape`。** 每六小时运行一次(`0 */6 * * *`),或者根据需要配合页面计数运行。它还原数据库,获取新摄像头,保存数据库,然后调用 `build`。这是唯一使用 `SHODANTOKEN` secret 的工作流。
**`youtube`。** 根据需要添加或刷新一个流。给它一个 YouTube URL 和可选的标签;它还原数据库,获取该视频的元数据和缩略图,保存数据库,然后调用 `build`。这是唯一使用 `YOUTUBE_API_KEY` secret 的工作流,并且它不安装任何额外的二进制文件。位于 `in/youtube.md` 的批量列表未被提交,因此要在本地一次性提取多个流,请使用 `bun import --youtube`,随后运行 `bun sync --push`。
**`blacklist`。** 接收一个 IP 或主机名,移除匹配的摄像头,保存数据库,然后调用 `build`,以便网站将其删除。
**`unblacklist`。** 接收一个 IP 或主机名并将其从黑名单中清除。它不会重新构建网站,因为在下一次抓取重新添加该主机之前,不会有任何摄像头数据发生变化。
**`reorder`。** 接收一个 IP 和一个端口,将该端口的截图固定为主机的画廊卡片,保存数据库,然后调用 `build`,以便新卡片出现在网站上。
**`tag`。** 接收一个类型(cam、stream 或 feed)、一个引用(IP、视频 ID 或摄像头 ID)和一个标签,将该标签附加到该实体,保存数据库,然后调用 `build`,以便该标签出现在网站上。
**`untag`。** 接收与 `tag` 相同的类型、引用和标签,并从该实体移除该标签,保存数据库,然后调用 `build`,以便该标签从网站上消失。
**`feature` / `unfeature`。** `feature` 接收一个类型(cam 或 stream)和一个引用(摄像头的 IP,流为视频 ID)并将其添加到主页精选集合中;`unfeature` 接收相同的配对并将其移除。每一个都会保存数据库,然后调用 `build`,以便主页更新。
**`geo`。** 接收一个视频 ID、纬度和经度,在其 `cams` 行上分配该流的地图坐标,保存数据库,然后调用 `build`,以便该流出现在地图上。
### 数据库存储
`camhunting.sqlite` 对于 git 来说太大了(几百 MB,并且只会增长),因此它作为名为 `db-store` 的预发布资产存在,而不是在仓库中。每个更改数据库的工作流都会首先从该 release 还原它,并在完成时上传新副本。`build` 读取它而不进行保存。所有写入工作流共享一个并发组(`db-write`),因此定时抓取、YouTube 提取器和手动黑名单操作永远无法同时运行并相互破坏。`bun sync` 在你的机器和该资产之间移动数据,这就是你在本地进行的编辑能够显示在网站上的方式;请参见[本地编辑](#editing-locally)。
### 运行工作流
打开 Actions 标签页,选择工作流,然后选择“Run workflow”。`scrape` 接收可选的页面计数(默认为 2)。`youtube` 接收视频 URL 和可选的标签。`blacklist` 和 `unblacklist` 接收 IP 或主机名,`reorder` 接收 IP 和端口,`tag` 和 `untag` 接收类型、引用和标签,而 `feature` 和 `unfeature` 接收类型和引用。无效的输入会导致运行立即失败。
### 一次性设置
首次运行前:
1. **启用 Pages。** Settings → Pages → Source = GitHub Actions。
2. **添加 secrets。** 创建一个名为 `SHODANTOKEN` 的仓库 secret,如果你需要 YouTube 提取器,也请创建 `YOUTUBE_API_KEY`。
3. **播种 DB 存储。** 从你的机器上传你的本地数据库。如果你还没有数据库,请先运行 `bun initdb` 以创建一个全新的、已播种的 `camhunting.sqlite`,然后再上传它。
```
bun initdb # optional: creates a seeded, empty camhunting.sqlite
gh release create db-store --prerelease --title "SQLite store" --notes "camhunting.sqlite db. DO NOT DELETE!"
gh release upload db-store camhunting.sqlite
```
`uses:` 操作被固定到具体的 commit SHA。使用 `actions-up` 刷新它们。
## 图标归属
[cctv icons](https://thenounproject.com/browse/collection-icon/cctv-glyph-172739/) 由 [heyrabbit](https://thenounproject.com/creator/heyrabbit/) 提供
标签:BeEF, Bun, SQLite, 爬虫, 物联网搜索引擎, 自动化攻击