@browserless.io/反机器人分类器
纯无依赖的分类器,决定页面负载是否 被一个反机器人系统(Cloudflare, DataDome, Imperva, 外围X,DDoS-Guard,或通用块页.
该软件包可同时离线( 批次分数记录的页面快照)
和在运行时间服务(分类直播会话)内,以便"堵塞"
比率"在两地都意味着相同. 没有I/O,没有浏览器或
DOM 全球,没有
非决定性( 无) Date,没有 Math.random) 分类中的任何地方
路径——相同 Observation 总是产生同样的 Classification。 。 。 .
这个 Observation → Classification 合同
classify(observation, ruleset) 需要一个 Observation - 隐私被践踏
一页简况——和 Ruleset返回 a Classification。 。 。 .
Observation 频道
所有字段都是可选的;提供你能够捕捉到的一切.
| 外地 | 类型 | 频道 | 页:1 |
|---|---|---|---|
host | string | —— 说 | 只有主机,没有查询字符串 。 本身没有相应的频道. |
status | number | status | 主文档HTTP状态代码. |
headers | Record<string, string> | header | 响应头; 匹配前按键会小写. |
cookies | string[] | cookie | 设置曲奇 名称 只有——从不包含价值. |
finalUrl | string | document-url | 查询字符串已被呼叫者剥取 . |
title | string | title | page.title()。 。 。 . |
text | string | text | 完成的顶框 innerText。 。 。 . |
markup | string | dom 编号 : markup | 顶端已使用 outerHTML。 。 。 . |
frames | FrameObservation[] | { url?, text?, markup? } | 同源儿童框架(无) title —— 说 FrameObservation 只携带 url编号 :text编号 :markup),因此间断在一帧内被制成(例如Imperva's iframe#main-iframe仍可达到. |
来电者负责在建造前 进行隐私清洗
Observation: 脱去查询字符串, 滴出 cookie 值( 仅取名),以及
截线 markup/范围 markup 以任何物配主
保留.
Classification 字段
| 外地 | 类型 | 页:1 |
|---|---|---|
status | BlockStatus | 三态 : 'blocked' | 'clear' | 'inconclusive'。 。 。 . |
blocked | boolean | 方便时间 status === 'blocked'。 。 。 . |
inconclusive | boolean | 方便时间 status === 'inconclusive'。 。 。 . |
vendor | string? | 中标供应商(如:. 'cloudflare'),仅在 blocked。 。 。 . |
kind | Kind? | 'challenge' | 'block' | 'captcha' | 'rate-limit' | 'network-error'。 。 。 . |
confidence | number | 0..1中奖的卖家的吵闹得分. |
tier | Channel? | 胜者最强匹配频道. |
matched | MatchedSignal[] | 所有匹配的信号, { vendor, channel, marker, weight, note? }。 。 。 . |
reason | string | 人可读取摘要等. "Blocked (cloudflare/challenge): header cf-mitigated"。 。 。 . |
inconclusive 覆盖分类器无法分辨的情况——浏览器级别
网络出错( e)net::ERR_CONNECTION_RESET- 风格字符串,完全没有内容
被捕获,或者页面被采样,但空出。 处理
inconclusive 列为“不包括分数”,而不是 clear。 。 。 .
使用量
classify
import { classify, DEFAULT_RULESET } from '@browserless.io/anti-bot-classifier';
const result = classify(
{
host: 'example.com',
status: 403,
headers: { 'cf-mitigated': 'challenge' },
},
DEFAULT_RULESET,
);
// result.status === 'blocked'
// result.vendor === 'cloudflare'
// result.kind === 'challenge'
detectBlock (只有DOM的便利嘘声)
对于只有 title 编号 : text 编号 : markup (没有信头,
饼干、状态或最后的 URL ) —— 这是对
遗产 detectBlock分类
DEFAULT_RULESET 盖下:
import { detectBlock } from '@browserless.io/anti-bot-classifier';
const result = detectBlock(
document.title,
document.body.innerText,
document.documentElement.outerHTML,
);
// result: { status, blocked, inconclusive, reason }
超越或扩展规则
classify 将规则作为明确的论点
全球状态。 要自定义检测,请创建 Ruleset 从零开始,
或扩展 DEFAULT_RULESET 添加或替换 signals数字 :
import {
classify,
DEFAULT_RULESET,
type Observation,
type Ruleset,
} from '@browserless.io/anti-bot-classifier';
const myRuleset: Ruleset = {
...DEFAULT_RULESET,
signals: [
...DEFAULT_RULESET.signals,
{
vendor: 'acme-waf',
channel: 'header',
key: 'x-acme-block',
marker: 'B',
kind: 'block',
weight: 0.9,
note: 'x-acme-block header present',
},
],
};
const observation: Observation = {
status: 200,
headers: { 'x-acme-block': '1' },
};
classify(observation, myRuleset);
A 类 Ruleset 实值 { signals, structural?, networkErrorSignals, threshold, version }。 。 。 .
signals a. 与单一信道相匹配;
structural 条目为联署材料上游((o: Observation) => boolean用于
需要同时跨越多个字段(例如“空顶”)的图案
框架加一个Imperva Iframe"). 两种都带有 marker数字 : 'B'
(只有块——分数)或 'P' (始终——仅上下文,在
matched 但永远不要移动比分.
信心模式
仅 'B'标记信号有助于打分; 'P' 信号是
显示于 matched 永远不要动 confidence。 。 。 .
匹配 'B' 信号按 vendor 并合并通过
吵吵闹闹.. score = 1 − Π(1 − weightᵢ) 如此多的微弱信号来自
同一家供应商仍然可以无一例外地作出自信的裁决
信号需要自己确定 最高的供应商
噪音- OR 分数获胜; 页面被分类 blocked 当胜利时
分数是 ≥ ruleset.threshold,以及 clear (或 inconclusive,见上文)
否则。 每个信号的重量 DEFAULT_RULESET,以及
threshold (目前为 0.5),是继承遗产的占地者
探测器的布尔行为——它们与真实的块/清晰的结果相适应
从标注在将来的发行中, 而不是在这个包的当前形式.
隐私
Classification 只有元数据 : vendor, (中文(简体) ), kind, (中文(简体) ), status编号 :blocked编号 :
inconclusive, (中文(简体) ), confidence, (中文(简体) ), tier,以及 reason (单位:千美元) matched,哪个
本身只携带 vendor编号 :channel编号 :marker编号 :weight编号 :note) (中文(简体) ). 从来没有
回放回放后页内容, cookie 值, 或查询字符串 —— 仅使用
输入 Observation 你通过,分类者读到,但从来没有
返回任意部分.
发展
npm test # vitest
npm run build # tsc -> dist/