tuaisen

每日自动健康打卡(Python+腾讯云服务器)

1.配置需要

python3.7,Chrome或者Edeg浏览器,Chrome驱动或者Edge驱动

#需要配置selenium库,baidu-aip库,pillOW库,在终端执行以下命令
pip install selenium
pip install pillow
pip install baidu-aip

2.实现功能

1.模拟登录说唱大学微服务,需要百度OCR智能识别API接口识别验证码(免费获取)

2.虚拟位置信息填写,注释:其余信息保留上一天信息

3.反馈打卡信息到QQ邮箱,注释:需要自行配置POP3/ SMTP服务

4.挂到腾讯云服务上,每天定时自动打卡

3.参考链接

百度OCR智能识别的API调用链接

QQ邮箱配置链接

腾讯云服务器上运行(免费1个月)选择轻量应用服务器,我选的linux系统,这里的实例也是linux

4.linux服务器配置

参考腾讯文档,远程登录linux实例

1.以root登录

2.下载Python3.7,升级pip,yum,更换国内源

3.安装库,执行以下命令

pip3 install selenium
pip3 install pillow
pip3 install baidu-aip

4.在linux上安装谷歌浏览器和驱动

在目录 /etc/yum.repos.d/ 下新建文件 google-chrome.repo

cd /etc/yum.repos.d/
vim google-chrome.repo

vim命名编辑google-chrome.repo文件,输入如下内容:

[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub

具体操作:按i插入,按Esc,然后Shift+;,输入wq,然后按Enter退出

安装浏览器,依次输入以下命令

yum -y install google-chrome-stable --nogpgcheck

# 检查版本信息
google-chrome --version
# 找到google_chrome路径:我对应的路径是/usr/bin/google-chrome,输入路径创建软连接
which google-chrome
# 创建软连接
ln -s /usr/bin/google-chrome /bin/chrome

# 安装驱动
wget https://npm.taobao.org/mirrors/chromedriver/88.0.4324.96/chromedriver_linux64.zip
# 解压
yum -y install zip
unzip chromedriver_linux64.zip

# 转移chromedriver到/user/bin目录下
sudo mv chromedriver /usr/bin

# 解决root运行chrome问题
vim /opt/google/chrome/google-chrome
# 将最后一行改为如下:
exec -a "$0" "$HERE/chrome" "$@" --no-sandbox $HOME

将Python自动运行程序写到linux里:

vim automatic.py
# 然后把程序复制进去

测试运行:

python3 automatic.py

利用crontab定时运行python脚本:(输入如下命令)

crontab -e

# 从左到右依次表示分、时、日、月、周,设置为每天0:01自动打卡
1 0 * * * /usr/bin/python3 /root/automatic.py

# 启动服务
service crond restart

5.代码部分

有详细解释

import sys
import time
from aip import AipOcr
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from PIL import Image
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

class LogIn:
    def __init__(self, user, passwd, path, lat=30.630869, long=104.083748):
        self.target = \'https://wfw.scu.edu.cn/ncov/wap/default/index\'  # 说唱大学微服务地址
        self.username = str(user)  # 用户名
        self.password = str(passwd)  # 密码
        self.lat = lat  # 纬度
        self.long = long  # 经度
        self.path = path


    def main(self):
        attempt = 0
        print(\'\n准备\')
        chrome_options = webdriver.ChromeOptions()
        # 设置无界面显示参数,因为要放在linux服务器上运行,无法显示界面,调试的时候需要把下面五行注释掉,显示chrome界面
        chrome_options.add_argument(\'--no-sandbox\')
        chrome_options.add_argument(\'window-size=1920x1080\')
        chrome_options.add_argument(\'--disable-gpu\')
        chrome_options.add_argument(\'--hide-scrollbars\')
        chrome_options.add_argument(\'--headless\')

        s = Service(self.path)
        browser = webdriver.Chrome(service=s, options=chrome_options)# 加载 chromedriver,用edge的就去下载edgedriver
        print(\'开始\')
        while True:
            browser.delete_all_cookies()  # 清空cookie
            browser.get(self.target)
            try:  # 切换为账号密码登录
                browser.switch_to.frame(\'loginIframe\')  # 切换frame
                switch_element = WebDriverWait(browser, 10).until(
                    EC.element_to_be_clickable((By.XPATH, \'/html/body/div/div/div[2]/div[2]/div[1]/div/div[3]\'))
                ) # 找到对应元素位置
                switch_element.click() # 点击切换
            except Exception as error:
                print(\'network wrong...\n\', error)

            # 输入账号和密码
            input_user = browser.find_element(by=By.XPATH, value=\'/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[1]/div[2]/div/input\')
            input_user.send_keys(self.username)
            input_pwd = browser.find_element(by=By.XPATH, value=\'/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[2]/div[2]/div/input\')
            input_pwd.send_keys(self.password)
            time.sleep(1)

            # 截图验证码并识别(这里用的百度云的免费OCR),需要自行注册,不会的可以参考这篇博客:https://www.cnblogs.com/xiaowenshu/p/11792012.html

            ver_btn = browser.find_element(by=By.CLASS_NAME, value=\'van-field__button\')
            ver_btn.click()# 刷新验证码
            # 获取图片元素的位置
            loc = ver_btn.location
            # 获取图片的宽高
            size = ver_btn.size
            # 获取验证码上下左右的位置
            left = loc[\'x\']
            top = loc[\'y\']
            right = (loc[\'x\'] + size[\'width\'])
            botom = (loc[\'y\'] + size[\'height\'])
            val = (left, top, right, botom)

            print(loc)
            print(size)
            # 验证码截图保存到当前目录下ver.png
            # 打开网页截图
            browser.save_screenshot(\'full.png\')
            # 通过上下左右的值,去截取验证码
            pic = Image.open(\'full.png\')
            ver_pic = pic.crop(val)
            ver_pic.save(\'ver.png\')

            verification = self.Vertification(\'ver.png\')
            print(\'verification code:\' + verification) # 识别验证码完毕

            input_ver = browser.find_element(by=By.XPATH, value=\'/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[3]/div[2]/div/input\')
            input_ver.send_keys(verification)
            browser.find_element(by=By.XPATH, value=\'/html/body/div/div/div[2]/div[2]/div[2]/div[3]/button\').click()  # 点击登录
            time.sleep(5)  # 等待跳转
            if browser.current_url == self.target:
                break # 登录成功,退出循环
            attempt += 1
            if attempt == 5: # 有时候网页会卡,即使密码正确也登录不上去,每次循环尝试5次登录(一般5次内能登录上去)
                print(\'请检查账号密码,或稍后再试!\')
                browser.quit()
                sys.exit()

        # 获取地理位置并提交
        browser.execute_cdp_cmd(
            "Browser.grantPermissions",  # 授权地理位置信息
            {
                "origin": "https://wfw.scu.edu.cn/",
                "permissions": ["geolocation"]
            },
        )
        browser.execute_cdp_cmd(
            "Emulation.setGeolocationOverride",  # 虚拟位置
            {
                "latitude": self.lat,
                "longitude": self.long,
                "accuracy": 50,
            },
        )
        try:  # 提交位置信息
            area_element = WebDriverWait(browser, 10).until(
                EC.element_to_be_clickable((By.NAME, \'area\'))
            )
            area_element.click()
        except Exception as error:
            print(\'get location wrong...\n\', error)

        time.sleep(2)  # 等待位置信息


        """
        邮箱信息,没有单独写个函数,需要配置QQ邮箱,开启POP3/ SMTP服务,并获取授权码
        因为是提醒自己打卡,所以自己是发件人,自己是收件人
        填入授权码
        """
        # 建立邮箱信息
        my_sender = \'XXX@qq.com\'  # 发件人邮箱账号
        my_pass = \'XXX\'  # 发件人邮箱密码(当时申请smtp给的口令)
        my_user = \'XXX@qq.com\'  # 收件人邮箱账号

        browser.find_element(by=By.XPATH, value=\'/html/body/div[1]/div/div/section/div[5]/div/a\').click()  # 提交信息
        try:
            ok_element = WebDriverWait(browser, 3).until(
                EC.element_to_be_clickable((By.XPATH, \'/html/body/div[4]/div/div[2]/div[2]\'))  # 提交按钮
            )
            ok_element.click()
            print(self.username, \'success!\')

            WebDriverWait(browser, 3).until(
                EC.presence_of_element_located((By.XPATH, \'/html/body/div[5]/div/div[1]\'))  # 成功对话框标题
            )
            title_success = browser.find_element(by=By.XPATH, value=\'/html/body/div[5]/div/div[1]\').get_attribute("innerHTML")
            print(\'From website:\', title_success)

            msg = MIMEText(\'打卡成功\', \'plain\', \'utf-8\')
            msg[\'From\'] = formataddr(["终极打卡人", my_sender])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
            msg[\'To\'] = formataddr(["打工人", my_user])  # 括号里的对应收件人邮箱昵称、收件人邮箱账号
            msg[\'Subject\'] = "打卡提示"  # 邮件的主题,也可以说是标题

            server = smtplib.SMTP_SSL("smtp.qq.com", 465)  # 发件人邮箱中的SMTP服务器,端口是465
            server.login(my_sender, my_pass)  # 括号中对应的是发件人邮箱账号、邮箱密码
            server.sendmail(my_sender, [my_user, ], msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
            server.quit()  # 关闭连接
        except:
            info = browser.find_element(by=By.CLASS_NAME, value=\'wapat-title\').get_attribute(\'innerHTML\')
            print(\'From website |\', self.username, \':\', info)

            msg = MIMEText(\'打卡失败,请手动打卡\', \'plain\', \'utf-8\')
            msg[\'From\'] = formataddr(["终极打卡人", my_sender])
            msg[\'To\'] = formataddr(["打工人", my_user])
            msg[\'Subject\'] = "打卡提示"

            server = smtplib.SMTP_SSL("smtp.qq.com", 465)
            server.login(my_sender, my_pass)
            server.sendmail(my_sender, [my_user, ], msg.as_string())
            server.quit()
        browser.quit()

    """
    函数声明:
    调用百度OCR的API,需要输入以下API接口:
            APP_ID = \'***\'
            API_KEY = \'***\'
            SECRET_KEY = \'***\'
    传入截取图片url,传出识别结果字符串
    """
    def Vertification(self, url):

        # 创建AipOcr
        """ 你的 APPID AK SK """
        APP_ID = \'XXX\'
        API_KEY = \'XXX\'
        SECRET_KEY = \'XXX\'

        client = AipOcr(APP_ID, API_KEY, SECRET_KEY)

        # 文字识别高精度版本

        """ 读取图片 """
        def get_file_content(url):
            with open(url, \'rb\') as fp:
                return fp.read()

        image = get_file_content(\'ver.png\')

        """ 调用通用文字识别(含位置高精度版) """
        result = client.accurate(image)
        print(str(result))
        res = result[\'words_result\'][0][\'words\']
        return str(res)

        # """ 如果有可选参数 """
        # options = {}
        # options["recognize_granularity"] = "big"
        # options["detect_direction"] = "true"
        # options["vertexes_location"] = "true"
        # options["probability"] = "true"
        #
        # """ 带参数调用通用文字识别(含位置高精度版) """
        # client.accurate(image, options)


if __name__ == \'__main__\':

    """
    用户输入区:
    学号用户名
    密码(一般为身份证后六位)
    定位地点的经纬度
    """
    username = \'XXX\'  # 用户名(学号)
    password = \'XXX\'  # 密码
    latitude = 30.630869  # 虚拟位置纬度
    longitude = 104.083748  # 经度

    path = \'.\chromedriver\chromedriver.exe\' #chromedriver路径
    # path = \'/usr/bin/chromedriver\' # linux服务器上的chromedriver路径
    t = LogIn(user=username, passwd=password, lat=latitude, long=longitude, path=path)
    t.main()

运行结果图:
file

分类:

技术点:

相关文章:

  • 2021-11-30
  • 2021-11-02
  • 2021-12-07
猜你喜欢
  • 2021-09-19
  • 2021-09-19
  • 2021-07-30
  • 2021-11-30
  • 2021-12-15
相关资源
相似解决方案