1、使用场景
编写脚本抓取微信首页聊天列表带数字红点的私聊好友昵称,过滤群聊、底部导航栏、顶部小程序板块、页面日期文字。
2、现象
脚本可以正常捕获页面所有数字红点控件(红点数量稳定识别为 3 个,对应 2 条私聊红点 + 底部微信 tab 红点);
向上递归父布局读取 Text 文本时,会连带抓取到顶部小程序区域、发现页入口、各类系统固定文字(最近使用的小程序、视频号、朋友圈、常用的小程序、收钱吧、直播、游戏、微信 (2)、各类日期「昨天 / 周三」);
已使用「黑名单数组过滤无效文字 + 过滤时间格式:+ 过滤纯数字 + 昵称长度≥2」多层规则,但是微信首页顶部的小程序区块也存在红点,布局层级和私聊会话条目结构一致,代码无法从布局层级区分「真实私聊条目」和「顶部小程序模块条目」,一直误识别系统文字当作好友昵称。
3、我方已做的处理
递归向上多层父容器,收集当前红点所在布局下全部 TextView 文本;
构建黑名单拦截所有已知系统固定文案、日期、底部 tab 文字;
增加格式校验:剔除纯数字、带冒号的时间字符串、长度小于 2 的字符;
筛选同级最短文本当作昵称。
4、请问:
有没有控件 ID / 布局 ID可以精准区分:微信首页「聊天列表 Item 条目」VS「顶部小程序布局条目」;
有没有微信会话条目的专属 className、布局特征,用来精准定位真正的聊天条目红点,排除页面其他区域红点;
微信新版首页会话条目标准的抓取稳定写法?

HAMI_6893877807 · 3 小时前

回答

Hamibot AI
1
· 3 小时前

针对微信首页抓取带数字红点的私聊好友昵称,解决顶部小程序区域误识别的问题,核心思路是利用控件位置和布局特征进行精准过滤,而非依赖不稳定的 id。微信的控件 id 随版本变化,不能作为区分依据。

1. 有没有控件 ID 或布局 ID 可以区分聊天列表 Item 与顶部小程序条目?

没有。 微信的控件 id 在每次更新后都可能变化,且聊天条目与小程序条目在 id 上并无稳定差异。因此,不能通过 id 来区分二者。

2. 微信会话条目的专属 className 或布局特征是什么?

聊天会话条目在布局上具有以下稳定特征(与小程序条目不同):

  • 包含头像:存在一个 android.widget.ImageView(好友头像)。
  • 包含至少两个 TextView:一个用于昵称,另一个用于消息预览或时间。
  • 红点位置:红点数字通常位于头像右上角,属于头像布局的子控件。

顶部小程序条目通常只有一个小程序图标(ImageView)和一个 TextView(小程序名称),缺少消息预览文本,且红点出现的位置和上下文不同。利用这些特征可有效过滤。

3. 微信新版首页会话条目标准抓取写法

以下脚本基于 位置过滤 + 布局特征校验,稳定提取私聊好友昵称,兼容不同微信版本,不使用箭头函数等新语法。

// 文档地址 https://docs.hamibot.com/

// 获取所有数字红点(匹配1-99+)
var redDots = textMatches(/^\d+$/).find();
var screenHeight = device.height;

// 黑名单(可根据实际系统文字扩充)
var blacklist = [
    "微信", "发现", "通讯录", "我",
    "小程序", "最近使用", "视频号", "朋友圈",
    "常用", "收钱吧", "直播", "游戏", "微信 (2)"
];

redDots.forEach(function(redDot) {
    var bounds = redDot.bounds();
    // 1. 过滤底部导航栏红点(屏幕底部 8% 区域)
    if (bounds.bottom > screenHeight * 0.92) return;
    // 2. 过滤顶部固定区域红点(屏幕顶部 15% 区域,包含搜索框和小程序入口)
    if (bounds.top < screenHeight * 0.15) return;

    // 3. 向上找到包含头像和文本的聊天条目容器
    var parent = redDot.parent();
    while (parent && parent.childCount() < 2) {
        parent = parent.parent();
    }
    if (!parent) return;

    // 4. 必须存在头像 ImageView
    var avatar = parent.findOne(className("android.widget.ImageView"));
    if (!avatar) return;

    // 5. 收集所有 TextView
    var texts = parent.find(className("android.widget.TextView"));
    var nickname = null;
    var hasSecondText = false; // 是否有消息预览/时间等第二个文本

    for (var i = 0; i < texts.length; i++) {
        var t = texts[i].text();
        if (!t) continue;
        // 过滤纯数字、时间格式、过短文本
        if (/^\d+$/.test(t)) continue;
        if (/^\d{1,2}:\d{2}$/.test(t)) continue;
        if (t.length < 2) continue;
        // 过滤日期
        if (/昨天|今天|星期|周|月|日/.test(t) && t.length <= 3) continue;
        // 黑名单过滤
        if (blacklist.indexOf(t) >= 0) continue;

        if (!nickname) {
            nickname = t; // 第一个符合条件的行为昵称
        } else {
            hasSecondText = true; // 存在第二个文本,确认为聊天条目
        }
    }

    // 6. 必须同时存在昵称和第二个文本(消息预览/时间),才能确认为会话条目
    if (nickname && hasSecondText) {
        console.log("私聊好友昵称: " + nickname);
        // 可在此处添加群聊过滤,如昵称包含“群聊”则跳过
    }
});

原理说明

  • 位置过滤:底部导航栏和顶部固定区域的红点坐标有明确区间,先用坐标排除。
  • 布局特征:真正的聊天条目必然包含头像(ImageView)和至少两个文本区域(昵称 + 消息预览),而小程序条目通常只有一个文本,无法满足条件。
  • 文本智能筛选:在父布局内提取所有 TextView,通过黑名单、格式校验和长度规则定位昵称,并确保存在第二个文本,从而精准识别会话条目。

此方法不依赖 id,完全基于布局结构和坐标,可稳定适配微信新版首页。

ℹ️ 内容由 AI 生成,可能不准确,请注意核实