短信过滤 APP 开发

news2024/9/20 1:10:52

fa9b3da6fb9f00e364dcb52768e599c9.jpeg

c3fd2a3775756ff5919ce38fe674fbf6.gif

本文字数:7033

预计阅读时间:42分钟

58907eb106b96b9717334be7d5bc3c5b.png

一直想开发一个自己的短信过滤 APP,但是一直没有具体实施,现在终于静下心来,边开发边记录下整体的开发过程。

01

垃圾短信样本

遇到的第一个问题是,既然要过滤垃圾短信,那首先要识别哪些是垃圾短信?如何识别呢?

参考之前训练识别钢管计数的经验,决定通过 CoreML 训练 Text 模型来识别,那问题来了,要训练模型的短信数据集怎么来?

一开始打算网上找到垃圾短信样本,但找了好久没找到,于是就想到用自己和家人手机里的短信,毕竟手机里短信一般不删除,也有小几千条,而且垃圾短信、推销、广告之类的应有尽有。

所以问题就变成了,如何导出 iPhone 短信?

这里笔者也查了好久,找到的第三方软件基本都是需要收费,最终发现了一个免费导出的方案。

首先不加密备份手机到电脑,如下图,选中Back up all the data on your iPhone to this Mac,点击Back Up Now,等待备份完成,备份完成后,再点击Manage Backups :

a5563068adf59c05a58a8a3f6026bc79.png
备份界面

Manage Backups 点击后,界面如下,可以看到已备份的记录,右键选择 Show In Finder,在文件夹中打开:

e02d18800bc61b2e8794a698dbd3d2c7.png
管理备份

然后可以看到备份所在目录已打开,这时候需要找到文件名为 3d0d7e5fb2ce288813306e4d4636395e047a3d28的文件,这个文件就是短信备份的数据库文件。然后问题来了,怎么找呢?看到备份目录一个个文件夹是不是懵,这怎么找,很简单,搜索,点击右上角的搜索,直接把这个文件名输入即可,注意搜索的范围是当前文件夹:

26af3ab3706377e92ae5c4d3f72a430a.png
备份文件夹

搜索结果如下:

4f810e48ab3b84accb2cda6925dcfda9.png
短信备份数据库文件

然后把这个文件单独拷贝到另一个地方,比如桌面,再用数据库软件打开,比如SQLPro for SQLLite,打开如下:

c0edddf67eab9fca584027a255e05d3a.png
短信数据库文件打开

然后观察这个文件后发现,手机号和短信记录分布在不同表中,需要写一个 SQL 查出需要的内容,SQL 内容如下,参考 SQL to extract messages from backup,选中上图中Query,输入命令如下:

SELECT datetime(message.date, 'unixepoch', '+31 years', '-6 hours') as Timestamp, handle.id, message.text,
    case when message.is_from_me then 'From me' else 'To me' end as Sender
FROM message, handle WHERE message.handle_id = handle.ROWID AND message.text NOT NULL;

然后点击右上角的执行, 可以看到,把短信都筛选出来了:

34565a1d4fe8be1b89579a2febf64209.png

然后选中所有 row,右键选择Export result set as 导出CSV,即可导出 excel 格式的文件:

6ddfa3ae838d037c316c2846fafcd02d.png
导出短信

这样就获取到了所需的短信样本。

02

垃圾短信训练识别

有了样本之后,再来看如何训练识别,打算使用苹果的 CoreML识别,那么如何使用?样本格式的要求是什么样?训练需要多久?

先来看,创建一个文字训练的CoreML工程,选中 Xcode,点击Open Developer Tool,选中 CoreML 打开,如下图:

b3505a24e733b5d44bfc488b4275efb0.png
XcodeDevelperTool

然后选择文件夹,并点击新建New Document, 如下:

25361e24145b32ac002ccc64a20be20c.png
New Document

然后选中 Text Classification,如下图:

05b071fa484f08913d34fe0fea4f12b2.png
Text Classification

接着输入项目的名字和描述:

e7a17e0eee5de24e84a333654f6cfd62.png
项目描述

点击右下角创建,进入主界面,如下:

85e42a7f9f6f688d0f6455c691fd4988.png
主界面

点击 Traing Data 的详细说明,可以看到 CoreML 要求的文字识别的格式,支持 JSON 和 CSV 文件,格式如下:

ffeadbfd4b1132e69526e22a93f5b73a.png
格式

JSON 格式如下:

// JSON file
[
    {
        "text": "The movie was fantastic!",
        "label": "positive"
    }, {
        "text": "Very boring. Fell asleep.",
        "label": "negative"
    }, {
        "text": "It was just OK.",
        "label": "neutral"
    } ...
]

而 CSV 格式则是,一列 text ,一列 label

textlabel

这是一条普通短信

label1
这是一条垃圾短信label2

由于再前一步中,已经将短信导出为 CSV 格式,所以这里就需要把格式改为上图中格式即可,只剩下一个问题需要解决,即:label 有哪些取值?

要看 label 有哪些取值,需要先看系统短信的过滤逻辑是什么样?支持的过滤分类有哪些?否则自己想实现的分类,分组好了,最后发现系统不支持就尴尬了。

03

短信过滤分类

系统短信的过滤逻辑

参考 SMS and MMS Message Filtering,可以看到,开发者是没有权限创建新分组的,只能是针对收到未知联系人的 SMS 或者 MMS ,拦截返回指定的分类。

这里需要注意的是,根据文档的说法,短信过滤不支持 iMessage 和通讯录中联系人短信的过滤,仅支持未知联系人的 SMS 和 MMS

短信过滤,又分为本地判断过滤和服务端判断过滤,示意图如下:

818d422e58a5448d36447e3c34ff3fd3.png

短信本地过滤

c207390093007156f68b51234518f623.png

短信服务端过滤

按照文档的说法,即使是服务端过滤,APP 也是不能直接访问网络的,系统会和设置的服务器交互;而且 App Extension 不能通过共享  Group  写数据,故而短信仅能在 App Extension中获取到,不能存储,不能上传,从而保证隐私和安全。关于服务端过滤更多的实现,可以参考 Creating a Message Filter App Extension

再来看支持的过滤类型,ILMessageFilterAction大分类支持五种:

  • none 没有足够信息,不能判断,会展示信息,或进一步请求服务端判断过滤

  • allow 正常展示信息

  • junk 阻止正常展示信息,显示在垃圾短信分类下

  • promotion 阻止正常展示信息,显示在推送信息分类下

  • transation 阻止正常展示信息,显示在交易信息分类下

而其中又可以细分子分类,ILMessageFilterSubAction,具体含义可以参考ILMessageFilterSubAction

  • none

  • promotion 支持的子分类有

    • others

    • offers

    • coupons

  • transation 支持的子分类有

    • others

    • finance

    • orders

    • reminders

    • health

    • weather

    • carrier

    • rewards

    • publicServices

这里仅针对大分类做处理,具体的子分类不做详细过滤,所以需要训练的 label 有哪些取值就很明确了,过滤垃圾短信、推广信息、交易信息,至于 none 和 allow 不做区分,统一处理为 allow,所以总共需要训练的 label 取值有以下这些:

  • allow

  • junk

  • promotion

  • transation

然后就是针对导出短信的 CSV 文件,针对每条短信,添加对应的 label,这里只能手工,样本的大小和 label 定义决定后续识别的准确度,同时为了后续子分类的实现,建议实事求是,不要把比如 promotion 里的分到 junk 里。。。

每条短信样本都标记好了之后,就可以导入Create ML来训练,生成需要的模型,步骤如下——

首先导入数据集:

d1f395586b071420ec43cfa966623889.png
导入数据集

然后点击左上角的 Train

ebc2208a9017e02f7d159d18d1510e98.png
训练Train

等训练好了之后,可以点击 Preview ,模拟短信文本,看输出的预测,如下图:

410c4bf554c075a9fb3c235d3205a9ce.png
效果检测

最后,导出模型,供  APP  使用:

e4b8f0017a0fdfe553ae61a06b6ff7f5.png

导出模型

04

APP开发

新建项目,然后使用 "new bing生成图片" 来设计 APPIcon,再用 ChatGPT-4,来生成 APP 名字。然后添加 Message Filter Extension Target,如下图:

acda72101d6a8510d033d36d86fc041a.png
Message Filter Extension Target

在 MessageFilterExtension.swift 中,能看到苹果已经帮忙实现了基本的框架,只需要在框架对应// TODO: 的地方,加入对应的过滤逻辑即可。

然后导入训练结果集到项目中,注意 Target 要勾选主工程和 Message Filter Extension 的 Target,因为需要在这个 Target 中使用模型来实现过滤。

具体使用如下:

import Foundation
import IdentityLookup
import CoreML

import IdentityLookup

enum SMSFilterActionType: String {
    case transation
    case promotion
    case allow
    case junk
    
    func formatFilterAction() -> ILMessageFilterAction {
        switch self {
        case .transation:
            return ILMessageFilterAction.transaction
        case .promotion:
            return ILMessageFilterAction.promotion
        case .allow:
            return ILMessageFilterAction.allow
        case .junk:
            return ILMessageFilterAction.junk
        }
    }
}

struct SMSFilterUtil {
    static func filter(with messageBody: String) -> ILMessageFilterAction {
        var filterAction: ILMessageFilterAction = .none
        let configuration = MLModelConfiguration()
        do {
            let model = try SmsClassifier(configuration: configuration)
            let resultLabel = try model.prediction(text: messageBody).label
            if let resultFilterAction = SMSFilterActionType(rawValue: resultLabel)?.formatFilterAction() {
                filterAction = resultFilterAction
            }
        } catch {
            print(error)
        }
        return filterAction
    }
}

然后在MessageFilterExtension.Swift 中 offlineAction(for queryRequest: ILMessageFilterQueryRequest) -> (ILMessageFilterAction, ILMessageFilterSubAction) 方法调用,如下:

@available(iOSApplicationExtension 16.0, *)
  private func offlineAction(for queryRequest: ILMessageFilterQueryRequest) -> (ILMessageFilterAction, ILMessageFilterSubAction) {
      guard let messageBody = queryRequest.messageBody else {
          return (.none, .none)
      }
      let action = MWSMSFilterUtil.filter(with: messageBody)
      return (action, .none)
  }

这里需要注意下 APP 最低版本设置,ILMessageFilterSubAction只有 iOS 16 以上的手机才支持,而 ILMessageFilterSubAction 则是 iOS 14 以上。

如果想实现更精细的 SubAction 的过滤,则上面短信数据集的 label需要改为更精细的 label,然后训练出模型,再用来判断。

另外,ILMessageFilterQueryRequest 中可以获取到 sender 和 messageBody,所以如果想实现自定义规则,比如针对某个手机号设置对应的规则,则需要从  APP 中设置对应的规则,然后通过 Group 共享到 Extension ,然后在上面的方法里通过规则匹配。

05

总结

相信通过上面的步骤,大家都能开发出自己的短信过滤 APP。

上面的步骤是通过固定的训练模型来匹配的逻辑,步骤是:

  1. 获取短信数据集

  2. 通过 CoreML 使用数据集训练并生成模型

  3. 在项目中使用模型,进行判断

这种方式生成的模型其数据固定,每次更新模型需要重新训练并导入,然后更新 APP。是否有更好的方式呢?比如是否可以在 APP 中边训练边更新?又或者是否可以通过本地规则加本地模型加网络模型这种方式?

假设方案一:

首先,在 APP 中边训练边更新,大概思路如下——

更新模型,需要知道一条数据的内容和数据的分类,所以如果要在 APP 中训练模型,就需要通过另外的办法获取到分类,要不然用模型得到分类再回过头来训练模型,意义不大。所以通过自定义规则获取到数据分类,然后用数据和数据分类来更新模型,这种方式应该是可行的。

假设方案二:

然后来考虑更完善的一种方式,即通过本地规则加本地模型加网络模型的方式:

逻辑是首先通过本地规则匹配,如果本地规则匹配不到,则继续使用本地模型匹配,如果本地模型也匹配不到,则通过请求服务端,服务端另有一套不断训练更新的模型,来获取对应的分类,最后每次更新时把服务端当前对应最新的模型更新到项目中。

假设方案三:

方案二需要通过网络模型,假设的前提是服务端有一套不断训练更新的模型,那如果这个假设不存在?只有本地规则和本地模型,外加偶尔获取到的更新数据集,是否有办法在线更新本地模型?

目前本地模型是直接添加到APP 主 Bundle 中,可以考虑在首次启动时拷贝到 APP 和Extension 的共享 Group 中,每次打开 APP 时,判断模型是否有更新,有更新则下载替换这个目录下的模型文件。在 Extension 中,通过 URL 获取这个目录下的模型文件来进行过滤。

几种方案流程图如下:

f31c40bb54e43b6a86b8dec42044c17e.png
短信 APP 过滤流程图

总结如下:

921d8da306cee7854f275d55f611c2d6.png
短信过滤 APP 开发流程

参考:

  • SQL to extract messages from backup

https://apple.stackexchange.com/questions/300866/sql-to-extract-messages-from-backup)

Creating a Text Classifier Model

https://developer.apple.com/documentation/createml/creating-a-text-classifier-model

SMS and MMS Message Filtering

https://developer.apple.com/documentation/sms_and_call_reporting/sms_and_mms_message_filtering

Creating a Message Filter App Extension

https://developer.apple.com/documentation/sms_and_call_reporting/sms_and_mms_message_filtering/creating_a_message_filter_app_extension

ILMessageFilterAction

https://developer.apple.com/documentation/sms_and_call_reporting/ilmessagefilteraction

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/987918.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAR will be empty - no content was marked for inclusion!

现象 在对自建pom依赖组件打包时&#xff0c;出现JAR will be empty - no content was marked for inclusion!错误。 方案 在pom中怎么加packaging标签内容为pom&#xff0c;标识只打包pom文件 <?xml version"1.0" encoding"UTF-8"?> ...<grou…

MyBatis的逆向工程

文章目录 前言MyBatis的逆向工程创建逆向工程的步骤添加依赖和插件创建MyBatis的核心配置文件创建逆向工程的配置文件执行MBG插件的generate目标 QBC查询增改 总结 前言 MyBatis的逆向工程 正向工程&#xff1a;先创建Java实体类&#xff0c;由框架负责根据实体类生成数据库表…

《计算机网络安全》DNS与它的具体作用解析

初步了解DNS 个人介绍DNS定义DNS作用DNS的生活加速作用科普 个人介绍 &#x1f338;一名大四备考考研学子&#xff0c;喜欢前端&#xff0c;还有Android和JAVA开发 &#x1f332;爱看书和打游戏还有唱歌 &#x1f352;热爱编程和读古今中外名著 &#x1f33a;座右铭&#xff1…

JMeter 4.0 如何获取cookie

文章目录 前言JMeter 4.0 如何获取cookie1. 修改jmeter.properties 文件2. 添加HTTP Cookie 管理器3. 获取cookie信息 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天…

TikTok运营做不起来?IP如何选择?

作为跨境电商新蓝海&#xff0c;TikTok不断的加快自己推进电商业务的步伐&#xff0c;也吸引了越来越多的跨境商家入驻。但是很多人信心满满注册入驻后&#xff0c;却遇到了0播放&#xff0c;流量少&#xff0c;转化低的问题&#xff0c;Tiktok运营不起来&#xff0c;那你要注意…

大数据技术之Hadoop:MapReduce与Yarn概述(六)

目录 一、分布式计算 二、分布式资源调度 2.1 什么是分布式资源调度 2.2 yarn的架构 2.2.1 核心架构 2.2.2 辅助架构 前面我们提到了Hadoop的三大核心功能&#xff1a;分布式存储、分布式计算和资源调度&#xff0c;分别由Hadoop的三大核心组件可以担任。 即HDFS是分布式…

WebStorm2023新版设置多个窗口,支持同时显示多个项目工程

调整设置 Appearance & Behavior -> System Settings> Project open project in New window&#xff1a;

记录mac虚拟机安装centos7

一. 安装VMWare Fusion&#xff08;略&#xff09; 二. 寻找arm64架构mac能拉起来的centos7镜像&#xff08;略&#xff09; 参考 https://cloud.tencent.com/developer/article/2150583?areaSource106000.2&traceIdkybnG2SKASN5GqSBiSmu9 三. 从origin镜像安装后开始记…

想要获得更多的好评吗?电子商务人不可错过的文章

电子商务评论可以飙升销售额并改善您与客户的关系。积极的客户反馈是任何电子商务成功故事的关键。高客户满意度保证了回头客和新买家&#xff0c;这将使您的公司保持活力。推荐使用SaleSmartly&#xff08;SS客服&#xff09;这一客户服务平台&#xff0c;给您的客户带来更好的…

Geoserver发布shp、tiff、瓦片等格式的GIS数据

这里写目录标题 1 发布shp矢量数据1.1 添加shp作为数据源1.2 发布shp图层1.3 预览服务1.4 配置样式 2 发布Postgres数据库2.2 发布数据 3 发布 tif 栅格数据3.1 添加 tif 数据源3.2 发布tif数据3.3 预览服务3.4 配置地图样式 关于中文标注乱码的问题 1 发布shp矢量数据 发布sh…

归并排序和快速排序的两种实现

在此之前我们已经介绍过归并排序和快速排序&#xff1a;浅谈归并排序与快速排序&#xff0c;但其中的实现都是基于递归的。本文将重新温故这两种算法并给出基于迭代的实现。 目录 1. 归并排序1.1 基于递归1.2 基于迭代 2. 快速排序2.1 基于递归2.2 基于迭代 1. 归并排序 1.1 基…

github网站打不开,hosts文件配置

首先获取github官网的ip地址&#xff0c; 打开cmd&#xff0c;输入ping github.com 配置&#xff1a; #github 140.82.114.4 github.com 199.232.69.194 github.global.ssl.fastly.net 185.199.108.153 assets-cdn.github.com 185.199.110.153 assets-cdn.github.com 185.199…

RT7625E两级电液伺服阀放大器

RT6215M、RT6225M、RT7625M、RT7625E、RTJ01、RT7325M双喷挡式两级电液伺服阀适合对位置、力和速度进行闭环控制&#xff0c;分体式比例放大器&#xff0c;无摩擦双喷嘴-挡板控制级&#xff0c;动态响应高&#xff0c;高分辨率&#xff0c;低滞环&#xff0c;干式力矩马达的二级…

windows10使用wheel安装tensorflow2.13.0/2.10.0

安装过程 安装虚拟环境安装virtualenv安装满足要求的python版本使用virtualenv创建指定python版本的虚拟环境 安装tensorflow2.13.0安装tensorflow-docs直接下载使用wheel下载 在VSCode编辑器中使用虚拟环境下的包 安装虚拟环境 这里笔者使用的是 virtualenv进行虚拟环境搭建的…

【linux基础(1)】

目录 一.linux的特殊结构二.命令简介及其格式三.ls命令四.cd和pwd命令简介1.cd命令2.pwd命令3.小结 五.绝对路径和相对路径六.特殊路径符 一.linux的特殊结构 linux的目录结构是一个树形结构 windows系统可以拥有多个盘符&#xff0c;如c盘&#xff0c;D盘&#xff0c;E盘 lin…

【C++】C++动态内存管理

&#x1f3f3;️‍&#x1f308;C/C内存分布 说明&#xff1a; 1.我们的代码并非放在代码段里的&#xff0c;而是以文件的形式存在磁盘上的。 代码经过编译链接形成的二进制指令&#xff0c;才是放进代码段里的。&#xff08;即可执行代码&#xff09; 2.“abcd”如果没有被c…

Ubuntu系统重装nvidia gpu驱动

1. 卸载原驱动 sudo apt remove *cuda* sudo apt remove *nvidia* sudo /usr/bin/nvidia-uninstall sudo dpkg -l | grep ^rc | cut -d -f3 | sudo xargs dpkg --purge sudo rm -rf ~/.cuda-license-* sudo apt purge nvidia-cuda-toolkit sudo apt remove nvidia-driver-* s…

无涯教程-JavaScript - IMABS函数

描述 IMABS函数以x yi或x yj文本格式返回复数的绝对值(模)。 Excel中的复数 复数简单地以文本形式存储在Excel中。 当将格式为" a bi"或" a bj"的文本字符串提供给Excel的内置复数函数之一时,这被解释为复数。 复数函数可以接受简单数值,因为它等效…

【面试心得】系统调用

这个问题也是在九识面试的时候被问到的&#xff0c;当时我说就是像Shell&#xff0c;从用户态转移到内核态的过程&#xff0c;面试官让我说的详细一点&#xff0c;我就说不出来了&#xff0c;然后我就说了一些函数调用的过程&#xff0c;hhhh。 现在在这里做一个记录吧。 本文…

已经2023年了,你还不会手撕轮播图?

目录 一、前言二、动画基础1. 定时器2. left与offsetLeft3. 封装函数3.1 物体3.2 目标点3.3 回调函数 4.封装 三、基础结构3.1 焦点图3.2 按钮3.3 小圆点3.4 总结 四、按钮显示五、圆点5.1 生成5.2 属性5.3 移动 六、按钮6.1 准备6.2 出错6.2.1 小圆点跟随6.2.2 图片返回 6.3 b…