登录邮箱
试用Mac版

作为一只爬虫,遇到短信验证码,有什么妙招?

发布时间:2022-09-15


深圳市优梦网络科技有限公司拥有一支专业,团结,高效,敬业的渠道管理销售和售前售后服务队伍。竭诚期待和有志于在企业信息化建设,企业互联网应用服务领域有共同价值观和发展方向的公司携手合作,在阿里巴巴这个大平台上共同开创企业SAAS市场的美好明天!


之前我们了解了一些验证码的处理流程,比如图形验证码、滑块验证码、点选验证码等等,但是这些验证码都有一种共同的特点,那就是这些验证码的处理流程通常只需要在 PC 上完成即可,比如图形验证码如果在 PC 上出现,那么在 PC 上直接验证通过就好了,所有的识别、验证输入的流程都是在 PC 上完成的。



但还有一种验证码和此种情况不同,那就是手机验证码,比如 PC 上需要输入手机号,然后短信验证码需要发到手机上,然后再在 PC 上把收到的验证码输入即可通过验证。



那遇到这种情况,我们如何才能将这个流程给自动化呢?


验证码收发



通常来说,我们的自动化脚本会运行在 PC 上,比如打开一个网页,然后模拟输入手机号,然后点击获取验证码,接下来就需要输入验证码了。打开页面,输入手机号、点击获取验证码等流程我们可以非常容易地实现自动化,但是验证码被发送到手机上了,我们怎么能把它转到 PC 上呢?



为了自动化整个验证码收发的流程,这时候我们想要完成的就是——当手机收到一条短信的时候,它能够自动将短信转发到某处,比如一台远程服务器上或者直接发到 PC 上,在 PC 上我们可以通过一些方法再把短信获取下来并提取验证码的内容,然后自动化填充验证码即可。



那这里关键的部分其实就是怎样完成这两个步骤:


  • 如何监听手机收到了短信
  • 如何将手机短信转发到想要的位置



这两个步骤缺一不可,而且都需要在手机上完成。



解决思路自然很简单了,我们以 Android 手机为例,如果有 Android 开发经验的话,其实这两个功能实现起来还是蛮简单的。


注意:这里我们仅仅简单介绍基本的思路,不会完全详细展开介绍具体的代码实现,感兴趣的话可以自行尝试。



首先如何监听手机收到了短信呢?



在 Android 开发中,整体就分为三个必要环节:


  • 注册读取短信的权限:在一个 Android App 中,读取短信是需要特定的权限的,所以我们需要在 Andriod App 的 AndroidManifest.xml 中将读取短信的权限配置好,比如接收短信的权限配置如下:

    <uses-permission android:name="android.permission.RECEIVE_SMS">uses-permission>
  • 注册广播事件:Android 有一个基本组件叫做 BroadcastReceiver,也就是广播接收者的意思,我们可以用它来监听来自系统的各种事件广播,比如系统电量不足的广播、系统来电的广播,当然系统收到短信的广播也就不在话下了。所以这就类似我们注册一个监听器,用来监听系统收到短信的事件。

    比如这里我们可以同样在  AndroidManifest.xml 里面注册一个 BroadcastReceiver,叫做 SmsReciver:

    <receiver android:name=".receive.SmsReciver">
       <intent-filter android:priority="999">
           <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
       intent-filter>
    receiver>
  • 实现短信广播接收:这里就需要我们真正实现短信接收的逻辑了,这里只需要实现一个 SmsReceiver 类来继承一个 BroadcastReceiver 然后实现其 onReceive 方法即可,其中 intent 参数里面便包含了我们想要的短信息内容,实现如下:

    public class SmsReciver extends BroadcastReceiver {

       @Override
       public void onReceive(Context context, Intent intent) {
           Bundle bundle = intent.getExtras();
           SmsMessage msg = null;
           if (null != bundle) {
               Object[] smsObj = (Object[]) bundle.get("pdus");
               for (Object object : smsObj) {
                   msg = SmsMessage.createFromPdu((byte[]) object);
                   Log.e("短信号码", "" + msg.getOriginatingAddress());
                   Log.e("短信内容", "" + msg.getDisplayMessageBody());
                   Log.e("短信时间", "" + msg.getTimestampMillis());
               }
           }
       }



如此一来,我们便实现了短信的接收。



短信收到之后,发送自然也就很简单了,比如服务器提供一个 API,我们通过请求该 API 即可实现数据的发送,这个通过 Android 的一些 HTTP 请求库就可以实现,比如 OkHttp 等构造一个 HTTP 请求即可,这里就不再赘述了。



不过总的来说,整个流程下来其实还需要花费一些开发成本的,对于如此常用的功能,有没有现成的解决方案呢?自然是有的。我们可以借助于于一些开源实现,我们就没必要重复造轮子了。



这里我们就介绍一个开源软件,叫做 SmsForwarder,中文翻译过来叫做短信转发器,其 GitHub 仓库地址为:https://github.com/pppscn/SmsForwarder。



它的基本流程架构图如下:



架构图非常清晰,SmsForwarder 可以监听监听收到短信的事件,获取到短信的来源号码、接受卡槽、短信内容、接收时间等内容,然后将其通过一定的规则转发出去,支持转发到邮箱、微信群机器人、企业微信、Telegram 机器人、Webhook 等。



比如我们可以配置类似这样的规则,如图所示:



比如当手机号符合一定的规则就转发到 QQ 邮箱,比如内容包含“报警”就转发到阿里企业邮箱,比如内容开头是“测试”就发动给叫做 TSMS 的 Webhook。



其中QQ邮箱、阿里企业邮箱都是我们已经配置好的发送方,都属于邮箱类型,TSMS 也是一种发送方,属于 Webhook 类型,如图所示:



我们也可以点击添加发送方按钮来添加对应的发送方,比如添加邮箱的发送方,我们可以设置 SMTP 配置下发件邮箱、SMTP 服务器、SMTP 端口、授权密码等内容:



设置 Webhook 我们可以选择是 GET 还是 POST 请求,然后填入对应的 URL、密钥等内容:



设置转发规则页面如图所示:



比如这里我们可以选择匹配卡槽、匹配的字段、匹配的模式,还可以配置正则来设置匹配的值,这里就配置了尾号是 4566 的手机号来执行一定的发送操作,收到的短信会发送到钉钉这个发送方。


实战演示



比如这里我们来尝试下,这里我们用 Flask 写一个 API,实现如下:


from flask import Flask, request, jsonify
from loguru import logger

app = Flask(__name__)


@app.route('/sms', methods=['POST'])
def receive():
   sms_content = request.form.get('content')
   logger.debug(f'received {sms_content}')
   # parse content and save to db or mq
   return jsonify(status='success')


if __name__ == '__main__':
   app.run(debug=True)



代码很简单,这里设置了一个路由,接收 POST 请求,然后读取了 Request 表单的内容,其中 content 就是短信的详情内容,然后将其打印出来。



我们将代码保存为 server.py,然后将其运行起来:


python3 server.py


<p style="margin: 0.8em 0px; padd