Skip to content

[Discussion] 也许是Bing搜索引擎的终极解决方案 #25

@Maritedo

Description

@Maritedo

LinkManager.user.jsBing 中效果不佳:

  • 时常出错,转换出的 url 指向错误或者格式非法;
  • 覆盖率低,大量 url 不会被处理。

因此,我对 bing 搜索的中转 url进行了分析以确定直接的转换方式,来更高效地将中转 url 替换为真实 url。

经过对中转页的分析。可以确定其为 BASE64 编码,并针对 BASE64 编码中与 URL编码 存在冲突的字符进行了替换。
分析如下:
GitHub - AirBashX/UserScript: 自用的油侯脚本 为例,该 URL 指向 https://github.com/AirBashX/UserScript(此处链接有所省略,完整链接可使用鼠标悬浮查看),URL 的请求参数表如下:

参数名 参数值
p 296180a42e2189e4JmltdHM9MTcyNjM1ODQwMCZpZ3VpZD0yMDQ1MWQ4My0yM2RjLTZiNWYtMjI0Ny0wOTJhMjJkNDZhYzYmaW5zaWQ9NTE4NQ
ptn 3
ver 2
hsh 3
fclid 20451d83-23dc-6b5f-2247-092a22d46ac6
psq AirBashX%2fUserScript
u a1aHR0cHM6Ly9naXRodWIuY29tL0FpckJhc2hYL1VzZXJTY3JpcHQ
ntb 1

其中,通过统计多对中转 url 和真实 url,可以发现随着真实 url 的长度变化,p 值长度变化小,u 值与真实 url 明显成正相关,可以考虑使用 BASE64 尝试进行解码。对于 BASE64 编码而言,编码的主体部分包含a-z, A-Z, 0-9, +/ 这64个字符,当最终 BASE64编码的长度并非 4 的倍数时,补 1~3 个 = 使其长度成为 4 的倍数。

统计更多的参数 u 及其对应的真实 url,可以发现每个 u 参数均以 a1 开始,结尾并不包含任何 =,删除 a1aHR0cHM6Ly9naXRodWIuY29tL0FpckJhc2hYL1VzZXJTY3JpcHQ 开头的 a1 后,其长度对 4 取余的结果为 3,在末尾加上一个 = 后使用 BASE64 可以解码得到 [https://github.com/AirBashX/UserScript](https://github.com/AirBashX/UserScript),由此,成功验证 u 为简单混淆后的 BASE64 编码。

尝试编写测试脚本后,存在部分报错,报错的中转 url 的 ua1L3RyYXZlbC9zZWFyY2g_cT13aW5kb3dzJWU1JTg4JTliJWU1JWJiJWJhJWU2JThjJTg3JWU1JTkwJTkxJWU3JWExJWFjJWU5JTkzJWJlJWU2JThlJWE1JWU3JTlhJTg0JWU5JTkzJWJlJWU2JThlJWE1Jm09ZmxpZ2h0cyZGT1JNPUZCU0NPUA,它包含了非 BASE64 编码字符 _,尝试将它替换为 +/ 后重新处理,最终在将 _ 替换为 / 并添加两个 = 后成功解码出原始字符串。同样的,可以验证 - 需要被替换为 +(实际上将 +/ 进行替换后的 BASE64 字符串被叫做 BASE64URL)。

因此,只需要在页面出现新增节点时,在新增节点树中查找 a 元素,判定其 url 是否为中转页后进行 BASE64URL 解码处理便可以得到真实 url,将得到的 url 重新设为 a 元素的 href 即可。

代码如下:

function handlerAnchor(a) {
    let url_ = a.href;
    if (url_.includes(".bing.com/ck/a?")) {
        let tmp = url_.slice(url_.lastIndexOf("u="));
        tmp = tmp.slice("u=a1".length, tmp.indexOf("&"));
        const paddingNeeded = 4 - tmp.length % 4;
        // 如果长度不是4的倍数,则需要补充'='
        if (paddingNeeded != 4) {
            tmp += '='.repeat(paddingNeeded);
        }
        try {
            let ori_url = atob(tmp.replace('-', '+').replace('_', '/'));
            a.href = ori_url;
        } catch (e) {
            console.log("Error parsing", tmp);
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions