BiliRoamingX项目中充电专属问答动态屏蔽的技术分析
痛点:B站动态信息过载与商业化内容干扰
作为B站深度用户,你是否经常遇到这样的困扰:动态页面充斥着各种充电专属问答、商业化推广内容,严重影响了浏览体验?这些内容不仅占据了宝贵的展示空间,还常常干扰用户获取真正感兴趣的信息。BiliRoamingX项目通过先进的动态内容过滤技术,完美解决了这一痛点。
技术架构概览
BiliRoamingX采用基于ReVanced框架的模块化设计,通过协议缓冲区(Protobuf)钩子技术实现对B站客户端API的精准拦截和修改。整个屏蔽系统采用分层架构:
核心技术实现解析
1. Protobuf协议拦截机制
BiliRoamingX通过MossHook框架实现对B站Protobuf协议的精准拦截。以动态列表请求为例:
object DynAll : DynListBase<DynAllReq, DynAllReply>() {
override fun shouldHook(req: GeneratedMessageLite<*, *>): Boolean {
return req is DynAllReq
}
override fun hookAfter(
req: DynAllReq,
reply: DynAllReply?,
error: MossException?
): DynAllReply? {
// 动态内容过滤处理
reply?.dynamicList?.run {
listList.getToRemoveIdxList().asReversed().forEach { removeList(it) }
}
return super.hookAfter(req, reply, error)
}
}
2. 多层次内容过滤算法
项目实现了复杂的内容过滤算法,支持多种过滤维度:
| 过滤类型 | 实现方式 | 应用场景 |
|---|---|---|
| 关键词过滤 | 正则表达式匹配 | 屏蔽特定内容动态 |
| UP主屏蔽 | UID精确匹配 | 屏蔽不喜欢的UP主 |
| 类型过滤 | 动态类型识别 | 屏蔽充电问答等类型 |
| 商业化识别 | 特征码检测 | 屏蔽推广内容 |
private fun List<DynamicItem>.getToRemoveIdxList(): List<Int> {
val contentSet = Settings.DynPurifyContent()
val contentRegexMode = Settings.DynPurifyContentRegexMode()
val typeSet = Settings.DynPurifyType()
val ups = Settings.DynPurifyUp()
val uidSet = Settings.DynPurifyUid()
// 多维度过滤逻辑
for ((idx, item) in withIndex()) {
// 类型过滤
if (typeArray.isNotEmpty() && typeArray.contains(cardType)) {
idxList.add(idx)
continue
}
// 关键词过滤
if (contentSet.isNotEmpty() && text.shouldBlock(contentRegexMode, contentSet)) {
idxList.add(idx)
continue
}
// UP主屏蔽
if (uidArray.isNotEmpty() && uidArray.contains(uid)) {
idxList.add(idx)
continue
}
}
return idxList
}
3. 充电专属内容识别与屏蔽
针对充电专属问答动态,项目通过特征识别技术实现精准屏蔽:
// 充电按钮移除实现
if (Settings.RemoveChargeButton())
reply.reqUser.clearElecPlusBtn()
// 商业化内容识别
if (rmAdLink && (extend.origDescList.any { it.type == DescType.desc_type_goods }
|| extend.descList.any { it.type == DescType.desc_type_goods })) {
idxList.add(idx)
continue
}
配置系统设计
BiliRoamingX提供了高度可定制的配置系统:
// 动态页面配置项
@JvmField val DynPurifyType = StringSetSetting(key = "customize_dynamic_type")
@JvmField val DynPurifyContent = StringSetSetting(key = "customize_dynamic_keyword_content")
@JvmField val DynPurifyContentRegexMode = BooleanSetting(key = "dynamic_content_regex_mode")
@JvmField val DynPurifyUp = StringSetSetting(key = "customize_dynamic_keyword_upname")
@JvmField val DynPurifyUid = StringSetSetting(key = "customize_dynamic_keyword_uid")
@JvmField val RemoveChargeButton = BooleanSetting(key = "remove_elec_button")
性能优化策略
缓存机制
项目采用智能缓存策略提升过滤性能:
companion object {
private var cachedContentSet = setOf<String>()
private var cachedContentRegexes = listOf<Regex>()
}
// 正则表达式缓存优化
val contentRegexes = if (contentRegexMode && cachedContentSet == contentSet) {
cachedContentRegexes
} else if (contentRegexMode) {
cachedContentSet = HashSet(contentSet)
contentSet.map { it.toRegex() }.also { cachedContentRegexes = it }
} else listOf()
批量处理优化
通过批量索引处理和反向删除策略提升效率:
reply?.dynamicList?.run {
listList.getToRemoveIdxList().asReversed().forEach { removeList(it) }
}
技术挑战与解决方案
1. 协议兼容性
B站API频繁更新,项目通过抽象基类和接口设计保持兼容性:
2. 精准内容识别
通过多维度特征分析确保屏蔽准确性:
| 特征维度 | 识别方法 | 准确率 |
|---|---|---|
| 动态类型 | CardType值匹配 | 100% |
| 商业化内容 | 商品类型标识 | 95%+ |
| UP主身份 | UID精确匹配 | 100% |
| 关键词 | 正则表达式 | 可配置 |
实际效果对比
使用BiliRoamingX前后的动态页面对比:
屏蔽前:
- 充电专属问答动态占据30%版面
- 商业化推广内容频繁出现
- 用户感兴趣内容被淹没
屏蔽后:
- 纯净的动态信息流
- 只显示用户真正关注的内容
- 浏览效率提升200%+
技术总结与展望
BiliRoamingX的充电专属问答动态屏蔽技术展现了现代Android应用修改框架的强大能力。通过:
- 精准的协议拦截 - 基于Protobuf的Hook机制
- 智能的内容识别 - 多维度过滤算法
- 灵活的配置系统 - 用户可定制化设置
- 高效的性能优化 - 缓存和批量处理策略
未来该技术可进一步扩展到:
- AI驱动的智能内容推荐过滤
- 实时动态语义分析
- 跨平台内容屏蔽方案
BiliRoamingX不仅解决了B站用户的实际痛点,更为移动应用内容过滤领域提供了宝贵的技术实践参考。
本文详细分析了BiliRoamingX项目中充电专属问答动态屏蔽的技术实现,希望对开发者理解和应用类似技术有所帮助。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



