智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)

1 前言

像华为watch3这款智能手表,不带短信功能,一号双终端的设备,三大运营商都不支持短信服务,手机不在身边收取短信如验证码、快递信息等很不方便,因此开发出此方法,解决信息读取问题。

2 思路

  1. 手表端安装QQ软件(有教程,自己搜一下);

  2. 利用手机APP smsfowarder (短信转发器)将手机短信实时转发到网页上(https://msg.allmything.com/);

  3. 利用Python爬虫爬取短信内容,获取最新的短信;

  4. 利用nonebot和go-cqhttp搭建QQ机器人(使用另一个QQ号),实时监控网页短信变化,发送到手表端QQ号上,实现短信读取;

  5. 程序可以全天候挂着,短信收取延时在5秒内。

3 步骤

  • 手机端

    1. 安装smsfowarder (短信转发器),应用锁,后台允许允许,防止杀后台;

      image-20210805170451767

    2. smsfowarder设置,设置发送方,添加发送方,选择发送到Webhook

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第1张图片

      具体的地址及token在我发的网址中有具体设置(https://msg.allmything.com/)

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第2张图片

      这样就可以将手机短信推送到网页了,可以在手机端测试是否设置成功

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第3张图片

    3. 注意:**验证码之类的短信有的手机有保护无法转发,解决方法以华为手机为例,右上角点击进入设置,取消选中验证码安全保护即可**

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第4张图片

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第5张图片

  • 爬虫 思路:界面登录,获取登录后的消息界面,解析源码,用正则表达式提取出短信信息 以下代码仅用于测试是否能够爬取成功,没用到最终代码中

    1. 界面需要登录(思路一:session会话保持,失败,页面没有cookies)

       ```python
       # -*- coding: utf-8 -*-
       # @FileName: message.py
       # @Author  : XuLei
       # @Time    : 2021/8/4 16:24
       # @Software: PyCharm
       # @Version : 1.0
       ​
       ​
       import random
       import requests
       ​
       ​
       # 生成随机的UserAgent
       def get_random_useragent():
           """生成随机的UserAgent
           :return: UserAgent字符串
           """
           USER_AGENTS = [
               "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
               "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36",
               "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36",
               "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36",
               "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 4.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
               "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
               "Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36",
               "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36",
               "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2309.372 Safari/537.36",
               "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2117.157 Safari/537.36",
               "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36",
               "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1866.237 Safari/537.36",
               "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F",
               "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36 Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10",
               "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.517 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36",
               "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36",
               "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36",
               "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1623.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36",
               "Mozilla/5.0 (X11; CrOS i686 4319.74.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1467.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1464.0 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1500.55 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
               "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
               "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
               "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.90 Safari/537.36",
               "Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36",
               "Mozilla/5.0 (X11; CrOS i686 3912.101.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17",
               "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1309.0 Safari/537.17",
               "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.15 (KHTML, like Gecko) Chrome/24.0.1295.0 Safari/537.15",
               "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.14 (KHTML, like Gecko) Chrome/24.0.1292.0 Safari/537.14"
           ]
           return random.choice(USER_AGENTS)
       ​
       # 创建session对象,可以保存Cookie值
       session = requests.session()
       ​
       # 处理headers
       headers = {
                   "user-agent": get_random_useragent()
               }
       ​
       # 需要登录的邮箱和密码
       data = {"loginphone": "", "loginemail": "邮箱", "password": "密码"}
       ​
       # 发送附带用户名和密码的请求,并获取登录后的Cookie值,保存在session里
       url = "https://api.sl.willanddo.com/api/msg/loginRegister"
       r = session.post(url, headers=headers, data=data)
       print(r.json())    # 打印登录状态是否成功
       ​
       #  session包含用户登录后的Cookie值,可以直接访问那些登录后才可以访问的页面
       response = session.get("https://msg.allmything.com/", headers=headers)
       ​
       # 打印响应内容
       response.encoding = "utf-8"    # 需要重新编码不然中文会乱码
       # print(response.text)
       ```
    2. 思路二:用selenium模拟浏览器登录,成功

       # -*- coding: utf-8 -*-
       # @FileName: message2.py
       # @Author  : XuLei
       # @Time    : 2021/8/4 19:18
       # @Software: PyCharm
       # @Version : 1.0
       ​
       from selenium import webdriver
       import time
       import re    # 正则表达式,文字匹配
       ​
       # 创建 WebDriver 对象,指明使用chrome浏览器驱动
       wd = webdriver.Chrome(r'C:\Users\13589\Desktop\chromedriver_win32_2\chromedriver.exe')
       ​
       # 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
       wd.get('https://msg.allmything.com/loginRegister.html')
       ​
       # 根据id选择元素,返回的就是该元素对应的WebElement对象
       element_email = wd.find_element_by_id("loginemail")
       element_password = wd.find_element_by_id("password")
       ​
       # 通过该 WebElement对象,就可以对页面元素进行操作了
       # 比如输入字符串到 这个 输入框里
       element_email.send_keys('邮箱')
       element_password.send_keys('密码\t\n')    # \t是tab键\n是enter键,模拟点击登录
       ​
       findmessages = re.compile(r'class="card">(.*?)')
       ​
       time.sleep(6)
       html = wd.page_source   # 提取网页源码
       print(html)
       messages = re.findall(findmessages, html)
       ​
       while messages==[]:
           time.sleep(1)
           html = wd.page_source  # 提取网页源码
           messages = re.findall(findmessages, html)
           print(messages)
       ​
       ​
       message_newest = messages[::-1]
       ​
       ​
       while True:
           html = wd.page_source  # 提取网页源码
           messages = re.findall(findmessages, html)
           if message_newest!=messages[::-1]:
               message_newest.append(messages[0])
               # send to QQ
               message_send = str(message_newest[-1])
               print(message_send)
           else:
               print("无新消息")
               time.sleep(1)
  • 利用nonebot和go-cqhttp搭建QQ机器人实现消息转发(视频教程可看:https://www.bilibili.com/video/BV1JK4y1D7kX?p=1)

    使用的是nonebot2.0版本,用过1.0的要先卸载,主页:https://v2.nonebot.dev/

    1. 安装nonebot(我的python环境用annoconda建立的虚拟环境,在pycharm的Terminal中安装的,你们也可以直接在cmd中安装) 输入以下命令(使用的豆瓣源比较快):

       pip install nb-cli -i https://pypi.douban.com/simple

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第6张图片

      顺带安装安装 NoneBot CQHTTP 适配器,后面使用go-cqhttp时要用到,提前装上

       pip install nonebot-adapter-cqhttp -i https://pypi.douban.com/simple
    2. nonebot初步设置 先创建一个空项目,如果是在虚拟环境中创建,就在虚拟环境下输入,不是就在想要创建的目录下shift+右键打开powershell输入以下命令

       nb create

      之后输入项目名称、插件放置位置(一般在src中)、是否加载内置插件选y,确认选y

      创建完之后项目文件夹下会有如下文件(修改.env和bot.py就行)

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第7张图片

      .env中将ENVIRONMENT=dev修改为ENVIRONMENT=prod bot.py修改为如下代码:

       #!/usr/bin/env python3
       # -*- coding: utf-8 -*-
       ​
       import nonebot
       from nonebot.adapters.cqhttp import Bot as CQHTTPBot
       ​
       # Custom your logger
       # 
       # from nonebot.log import logger, default_format
       # logger.add("error.log",
       #            rotation="00:00",
       #            diagnose=False,
       #            level="ERROR",
       #            format=default_format)
       ​
       # You can pass some keyword args config to init function
       nonebot.init()
       app = nonebot.get_asgi()
       ​
       driver = nonebot.get_driver()
       driver.register_adapter("cqhttp", CQHTTPBot)
       nonebot.load_builtin_plugins()
       nonebot.load_from_toml("pyproject.toml")
       ​
       # Modify some config / config depends on loaded configs
       # 
       # config = driver.config
       # do something...
       ​
       ​
       if __name__ == "__main__":
           nonebot.logger.warning("Always use `nb run` to start the bot instead of manually running!")
           nonebot.run(app="__mp_main__:app")
    3. go-cqhttp设置(文档地址:https://docs.go-cqhttp.org/) 下载单独的go-cqhttp.exe文件,下载地址:https://github.com/Mrs4s/go-cqhttp/releases 下载完先运行一下,有的第一次要选功能(我直接12345全选了),生成其它的文件,关闭

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第8张图片

      然后需要修改config.yml文件,可以参考官网,需要修改两个地方一个是你要用的QQ号和密码,一个是反向WS设置,直接复制我下面的代码替换就可以了。

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第9张图片

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第10张图片

       # 反向WS设置
         - ws-reverse:
             # 反向WS Universal 地址
             # 注意 设置了此项地址后下面两项将会被忽略
             # universal: ws://your_websocket_universal.server
             universal: ws://127.0.0.1:8080/cqhttp/ws
             # 反向WS API 地址
             # api: ws://your_websocket_api.server
             api: ""
             # 反向WS Event 地址
             # event: ws://your_websocket_event.server
             event: ""
             # 重连间隔 单位毫秒
             reconnect-interval: 3000
             middlewares:
               <<: *default # 引用默认中间件

      这个时候在运行go-cqhttp.exe程序,就可以登录了

      将nonebot和go-cqhttp.exe关联,先运行bot.py文件,看到下面的就可以运行go-cqhttp了

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第11张图片

      再运行go-cqhttp.exe(可以双击、powershell、cmd中运行,也可以在pycharm中运行)

      智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第12张图片

      至此QQ机器人搭建完成

  • 将爬虫和QQ机器人结合,实现短信转发

    编写插件,在nonebot之前建的项目文件夹下的src目录中新建插件py文件(运行bot.py时,插件会自动加载)

    智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第13张图片

     # -*- coding: utf-8 -*-
     # @FileName: message_send.py
     # @Author  : XuLei
     # @Time    : 2021/8/4 21:52
     # @Software: PyCharm
     # @Version : 1.0
     ​
     ​
     from nonebot import require
     import nonebot
     from selenium import webdriver
     import time
     import re  # 正则表达式,文字匹配
     import os
     ​
     ​
     messagesend = ""
     ​
     # 创建 WebDriver 对象,指明使用chrome浏览器驱动
     wd = webdriver.Chrome(r'C:\Users\13589\Desktop\chromedriver_win32_2\chromedriver.exe')
     ​
     # 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
     wd.get('https://msg.allmything.com/loginRegister.html')
     ​
     # 根据id选择元素,返回的就是该元素对应的WebElement对象
     element_email = wd.find_element_by_id("loginemail")
     element_password = wd.find_element_by_id("password")
     ​
     # 通过该 WebElement对象,就可以对页面元素进行操作了
     # 比如输入字符串到 这个 输入框里
     element_email.send_keys('网页登录邮箱')
     element_password.send_keys('网页密码\t\n')
     ​
     findmessages = re.compile(r'class="card">(.*?)', re.S)
     ​
     message = ""
     ​
     scheduler = require("nonebot_plugin_apscheduler").scheduler
     @scheduler.scheduled_job("cron", second="*/5", id="sleep_sched")
     ​
     async def message_send():
         global message
         messagesend = await get_msg()
         print(messagesend)
         if messagesend!=None:
             if messagesend!=message:
                 print(messagesend)
                 bot = nonebot.get_bots()["QQ机器人的QQ号"]
                 await bot.call_api("send_msg", **{
                     "message": messagesend,
                     "user_id": "1358984514"
                 })
                 message=messagesend
     ​
     async def get_msg():
         html = wd.page_source  # 提取网页源码
         messages = re.findall(findmessages, html)
         print(messages)
         if len(messages)==0:
             return None
         else:
             return str(messages[0])

    至此整个短信转发项目就搭建完成了

和之前一样先运行bot.py文件,再运行go-cqhttp.exe程序就可以实时将手机短信转发到手表端的QQ上了,运行一下试试吧!

效果:

智能手表短信读取实现(带有eSIM卡,无短信功能,可安装手表QQ的智能手表)_第14张图片

你可能感兴趣的:(华为watch3,python,华为,harmonyos)