Kazumi icon indicating copy to clipboard operation
Kazumi copied to clipboard

解析模块迭代

Open Predidit opened this issue 8 months ago • 54 comments

评估使用 flutter_inappwebview 重构解析模块。

现有的解析机制的主要问题在于,我们没有办法在上层拦截并检查 webview 中的所有请求,我们需要这样做来获取视频直链。我们只能通过注入特殊的 JS 脚本来纂改 JS 执行环境间接达到目的。由于浏览器 CORS 限制的存在,我们注入的脚本的作用域不包含网页内嵌的 iframe 。我们不得不使用了大量不干净的方法来绕过这一限制,这导致了解析的相对缓慢,和部分站点的解析失败。

flutter_inappwebview 的文档中提到了一种可能适用于我们应用场景的功能,我们可以劫持所有 webview 内部的网络请求到 dart 层,并将 dart 层网络请求的结果返回 webview 内部。这听上去相当完美。

主要问题在于

  1. 涉及频繁的 PlatformChannel 通讯,我们需要通过平台通道快速转运 MB 级别的大型对象,这会造成明显的性能损失,且由于通讯过程中平台线程的阻塞,我们可能在解析时出现频繁的应用冻结甚至崩溃。我还没有测试这里实际的性能表现。

  2. 劫持所有请求到 dart 层意味着我们要处理可能出现的内嵌 iframe 中的可能存在的包含 referer 校验以及 JS 挑战机制,这基本无法解决,我们需要测试由此失效的规则数量是否可以接收。

  3. 破坏了跨平台一致性,新的插件不兼容 linux 以及 ohos,我们需要在这两个平台上继续使用之前的实现。

Predidit avatar Apr 20 '25 05:04 Predidit

ohos 适配有 6.0.0 版本的 flutter_inappwebview

ErBWs avatar Apr 20 '25 05:04 ErBWs

pichillilorenzo/flutter_inappwebview#2507

我们需要的方法只支持特定平台。更糟糕的是,此问题提到在支持的平台上,这一功能同样通过 JS 注入实现,并且同样不稳定。

此方案暂时搁置,考虑使用基于内置代理服务器的方案拦截网络请求。

Predidit avatar Apr 22 '25 04:04 Predidit

是否有跨域的规则示例可以测试?我可以尝试一下将 #1153 移植到 ohos 平台上,虽然根据我的搜索看上去不是很可行

ErBWs avatar Aug 07 '25 07:08 ErBWs

@ErBWs

girigirilove 规则关掉简易解析就可以测试跨域了

Predidit avatar Aug 07 '25 07:08 Predidit

经过简单测试,forMainFrameOnly 在 Android 上有效。

KotaHv avatar Aug 07 '25 10:08 KotaHv

@KotaHv

有兴趣建立一个新的PR替换android相关实现吗

Predidit avatar Aug 07 '25 10:08 Predidit

@ErBWs @KotaHv

#1153 导致了 windows 解析器的失败,主要问题在于 flutter 包含原生代码的插件的机制,如果我们引入的插件支持所有平台,那么所有平台都会包含对应的原生代码,即使在相应平台上相关插件从未被使用。

flutter_inappwebview 插件与 webview_windows 插件存在难以解决的冲突,且 flutter_inappwebview 在 windows 平台上的 user script 相关实现存在问题。这导致 windows 解析器无法使用。

这里的最佳实践似乎应该是引入

flutter_inappwebview_platform_interface: ^1.3.0+1
flutter_inappwebview_ios: ^1.1.2
flutter_inappwebview_macos: ^1.1.2

并使用 flutter_inappwebview_platform_interface 提供的 API ,而不是直接引入

flutter_inappwebview: ^6.1.5

这样可以保证我们只在想要的平台上编译 inappwebview 的原生代码,这有点像我们当时对亮度插件做的事情,但要复杂很多,由于相关尝试只能在 mac 上进行,有人对 #1153 的重构感兴趣吗。

Predidit avatar Aug 07 '25 14:08 Predidit

导致了 windows 解析器的失败,主要问题在于 flutter 包含原生代码的插件的机制,如果我们引入的插件支持所有平台,那么所有平台都会包含对应的原生代码,即使在相应平台上相关插件从未被使用。

flutter_inappwebview 插件与 webview_windows 插件存在难以解决的冲突,且 flutter_inappwebview 在 windows 平台上的 user script 相关实现存在问题。这导致 windows 解析器无法使用。

好的,我来对这部分进行重构。

KotaHv avatar Aug 07 '25 15:08 KotaHv

ohos 的适配看起来并没有适配好,ContentBlockerActionType.BLOCK 返回 null,ets 代码有做适配,但是 platform_interface 里没有增加对应的平台判断

不过我也不是很懂这里 content blocker 的作用是什么,不知道自行添加平台判断后是否可以使用

Image Image

ErBWs avatar Aug 08 '25 07:08 ErBWs

Content Blocker 主要是为了拦截 dmand 规则的 https://www.88dmw.com/template/dmd8pc/js/devtools-detector.js,这个会导致 src被重定向到 https://www.dmd8.com/。platform_interface 会调用该平台的实现,或许不用考虑 Content Blocker

KotaHv avatar Aug 08 '25 08:08 KotaHv

dmand 好像现在搜索不了?搜出来全是无结果,但是网页可以搜索

ErBWs avatar Aug 08 '25 08:08 ErBWs

是 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1' 造成的, 这个ua会导致访问移动版,我们应该将其从 userAgentsList 移除

KotaHv avatar Aug 08 '25 08:08 KotaHv

已经在主分支移除

Predidit avatar Aug 08 '25 08:08 Predidit

看起来 ohos 可能无法移植,移植后只有关闭简易解析的 girlgirlLove 可以正常解析,NT、xfdm、dmand 都无法正常解析

ErBWs avatar Aug 08 '25 09:08 ErBWs

看上去和 windows 平台的状况类似, 这些平台的模拟 User Script 支持相当不可靠

Predidit avatar Aug 08 '25 09:08 Predidit

我不知道 ohos 平台中有没有原生 User Script 支持, 如果有的话, 那应该是最终解决方案

Predidit avatar Aug 08 '25 09:08 Predidit

@KotaHv

我在查看 inappwebview 文档时注意到一个问题, UserScript 似乎会在 webview 后续加载的其他网页中继续生效.

考虑到我们注入的时机是 loadUrl , 这是否会导致每次切换选集时的重复注入, 这种重复注入是否会影响更换分集时的解析.

Predidit avatar Aug 08 '25 09:08 Predidit

我不确定原生 UserScript 的含义是什么,但这里看起来 ohos 是支持注入 js 到所有 frame 的,貌似默认注入所有 frame

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-webview-webviewcontroller#registerjavascriptproxy

ErBWs avatar Aug 08 '25 09:08 ErBWs

RegisterJavaScriptProxy 方法看上去更像是用来桥接, 而不是在所有 iframe 中执行特定用户脚本, 我不知道能否使用他来进行跨 iframe 的注入.

其次华为这部分的文档看上去相当暧昧, 完全没有提到 iframe 的跨域问题, 正常的浏览器安全策略对跨域和非跨域 iframe 的态度是完全不同的.

Predidit avatar Aug 08 '25 09:08 Predidit

@KotaHv

我在查看 inappwebview 文档时注意到一个问题, UserScript 似乎会在 webview 后续加载的其他网页中继续生效.

考虑到我们注入的时机是 loadUrl , 这是否会导致每次切换选集时的重复注入, 这种重复注入是否会影响更换分集时的解析.

换集时只会在 safari 控制台里提示:

  1. SyntaxError: Can't create duplicate variable: '_r_text'
  2. SyntaxError: Can't create duplicate variable: '_observer' 但不会影响到解析。

KotaHv avatar Aug 08 '25 09:08 KotaHv

Android 上也不是原生,是通过 prepareAndAddUserScripts 来实现注入

KotaHv avatar Aug 08 '25 09:08 KotaHv

@KotaHv

这个错误是 blob 解析脚本导致的, 其中的主要变量被声明为不可变, 在脚本被重复执行时尝试为不可变量重新赋值而抛出了错误

我们是否应该考虑修改 UserScript 的注入时机以解决重复注入的问题

Predidit avatar Aug 08 '25 09:08 Predidit

Android 上也不是原生,是通过 prepareAndAddUserScripts 来实现注入

ohos 看代码也是相同的方式来模拟注入。但是貌似安卓上可以正常工作?可以看一下适配安卓的代码吗?我怀疑是我移植上的问题或者 ohos webview 的问题

ErBWs avatar Aug 08 '25 09:08 ErBWs

@KotaHv

这个错误是 blob 解析脚本导致的, 其中的主要变量被声明为不可变, 在脚本被重复执行时尝试为不可变量重新赋值而抛出了错误

我们是否应该考虑修改 UserScript 的注入时机以解决重复注入的问题

可能不是注入时机的问题, _observer的注入时机是AT_DOCUMENT_END,可能是在iOS、macOS平台上之前注入的变量仍然存在于 JavaScript 上下文中? 可以通过在unloadPage里添加 await webviewController!.removeAllUserScripts();解决

KotaHv avatar Aug 08 '25 10:08 KotaHv

Android 上也不是原生,是通过 prepareAndAddUserScripts 来实现注入

ohos 看代码也是相同的方式来模拟注入。但是貌似安卓上可以正常工作?可以看一下适配安卓的代码吗?我怀疑是我移植上的问题或者 ohos webview 的问题

我还没开始适配Android,只是让 Android 使用 WebviewAppleItemControllerImpel 与 WebviewAppleItemImpel 进行了简单测试。

KotaHv avatar Aug 08 '25 10:08 KotaHv

那看上去主要还是 ohos 的 webview 的问题了,不知道为什么反而只有 girlgirllove 可以正常解析了

ohos 会出现一个问题是当一个规则解析成功后,切换到其他规则不会自动开始解析,会直接显示解析成功

ErBWs avatar Aug 08 '25 10:08 ErBWs

可能不是注入时机的问题, _observer的注入时机是AT_DOCUMENT_END,可能是在iOS、macOS平台上之前注入的变量仍然存在于 JavaScript 上下文中? 可以通过在unloadPage里添加 await webviewController!.removeAllUserScripts();解决

是的, 我上面的意思就是 UserScript 在 webview 的整个生命周期都是存在的, 并不会随着网页的重新加载而被移除, 上面的注入时机指的是我们要不要考虑在 webview 初始化时, 而不是加载网页时注册 UserScript

await webviewController!.removeAllUserScripts(); 听上去不错, 你可以测试这个实现吗, 主要测试有无控制台报错, 以及选集更换的问题

Predidit avatar Aug 08 '25 10:08 Predidit

那看上去主要还是 ohos 的 webview 的问题了,不知道为什么反而只有 girlgirllove 可以正常解析了

我怀疑可能是 webview 内部的安全策略问题, 正常情况下, CORS 会阻止我们对非同源 iframe 的一些操作

girigirilove 的情况比较特殊, 他的 iframe 域名和网页域名是相同的, 但是子域名不同

正常情况下 webview 应该判定这是非同源 iframe , 可能华为的 webview 认为这是同源的, 只有域名完全不同的 iframe 才是非同源的

Predidit avatar Aug 08 '25 10:08 Predidit

也许还是和注入时机有关,无法使用 webview 播放器进行播放

ErBWs avatar Aug 08 '25 10:08 ErBWs

可能不是注入时机的问题, _observer的注入时机是AT_DOCUMENT_END,可能是在iOS、macOS平台上之前注入的变量仍然存在于 JavaScript 上下文中? 可以通过在unloadPage里添加 await webviewController!.removeAllUserScripts();解决

是的, 我上面的意思就是 UserScript 在 webview 的整个生命周期都是存在的, 并不会随着网页的重新加载而被移除, 上面的注入时机指的是我们要不要考虑在 webview 初始化时, 而不是加载网页时注册 UserScript

await webviewController!.removeAllUserScripts(); 听上去不错, 你可以测试这个实现吗, 主要测试有无控制台报错, 以及选集更换的问题

添加 removeAllUserScripts 解决了控制台报错问题,换集解析在无论添加与否都正常运行 注入时机我还需要再测试看看

KotaHv avatar Aug 08 '25 10:08 KotaHv