每日自动健康打卡(Python+腾讯云服务器)
1.配置需要
python3.7,Chrome或者Edeg浏览器,Chrome驱动或者Edge驱动
#需要配置selenium库,ddddocr库,pillow库,在终端执行以下命令
pip install selenium
pip install pillow
pip install ddddocr
2.实现功能
1.模拟登录说唱大学微服务,需要ddddocr训练好的模型识别验证码
2.虚拟位置信息填写,注释:其余信息保留上一天信息
3.反馈打卡信息到QQ邮箱,注释:需要自行配置POP3/ SMTP服务
4.挂到腾讯云服务上,每天定时自动打卡
3.参考链接
QQ邮箱配置
免费的腾讯云申请
(这里没办法放上链接,相关可以百度)
4.linux服务器配置
1.以root登录
2.下载Python3.7,升级pip,yum,更换国内源
3.安装库,执行以下命令
pip3 install selenium
pip3 install pillow
pip3 install ddddocr
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,然后输入:,再输入qw,然后按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.代码部分
有详细解释,windows和centos7都适用
# -*- coding: utf-8 -*-
"""
@Time : 2022/7/11
@Author : PC
@File : daka
@Description :
"""
import sys
"这里填写linux的python包依赖路径"
sys.path += ['/usr/local/lib/python3.6/site-packages/', '/usr/local/lib64/python3.6/site-packages/']
import time
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 PIL import Image
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
import ddddocr
"""获取driver"""
def driver(driverpath):
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')
browser = webdriver.Chrome(executable_path=driverpath, options=chrome_options) # 加载 chromedriver,用edge的就去下载edgedriver
return browser
"""
验证码识别
"""
def ocr(path):
ocr = ddddocr.DdddOcr()
with open(path, 'rb') as f:
img_bytes = f.read()
res = ocr.classification(img_bytes) # numpy版本报错不影响,不要升级
return res
"""
更改chrome定位
"""
def setloca(browser, lat, long):
browser.execute_cdp_cmd(
"Browser.grantPermissions", # 授权地理位置信息
{
"origin": "https://wfw.scu.edu.cn/",
"permissions": ["geolocation"]
},
)
browser.execute_cdp_cmd(
"Emulation.setGeolocationOverride", # 虚拟位置
{
"latitude": lat,
"longitude": 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服务,并获取授权码
因为是提醒自己打卡,所以自己是发件人,自己是收件人
填入授权码
"""
def stamp(userstamp, flag):
# 建立邮箱信息
my_sender = 'xxxx@qq.com' # 发件人邮箱账号
my_pass = 'xxxx' # 发件人邮箱密码(当时申请smtp给的口令)
my_user = userstamp # 收件人邮箱账号
if flag:
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() # 关闭连接
else:
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()
"""
打卡程序主体
"""
def clock(username, password, url, lat, long, userstamp, browser):
browser.delete_all_cookies() # 清空cookie
browser.get(url)
attempt = 0
while True:
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(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(password)
time.sleep(0.5)
ver_btn = browser.find_element(by=By.CLASS_NAME, value='van-field__button')
ver_btn.click() # 刷新验证码
time.sleep(2)
# 获取图片元素的位置
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)
# 验证码截图保存到当前目录下code.png
# 打开网页截图
browser.save_screenshot('full.png')
# 通过上下左右的值,去截取验证码
pic = Image.open('full.png')
ver_pic = pic.crop(val)
ver_pic.save('code.png')
verification = ocr('code.png')
print('current 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 == url: # 检验登录成功
try:
browser.find_element(by=By.XPATH,
value='/html/body/div[2]/div/div[2]/div').click()
time.sleep(0.5)
except:
break
break # 登录成功,退出循环
attempt += 1
if attempt == 10: # 有时候网页会卡,即使密码正确也登录不上去,每次循环尝试5次登录(一般5次内能登录上去)
print('please check your usernumber and password, or try later')
browser.quit()
sys.exit()
setloca(browser, lat, long) # 设置地理位置
browser.find_element(by=By.XPATH,
value='/html/body/div[1]/div/div/section/div[5]/div/a').click() # 提交信息
try:
ok_element = WebDriverWait(browser, 5).until(
EC.element_to_be_clickable(
(By.XPATH, '/html/body/div[5]/div/div[2]/div[2]')) # 提交按钮
)
ok_element.click()
print(username, 'success clock')
WebDriverWait(browser, 5).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('message from website:', title_success)
flag = True
stamp(userstamp, flag)
except:
info = browser.find_element(by=By.CLASS_NAME,
value='wapat-title').get_attribute('innerHTML')
print('message from website:', username, ':', info)
flag = False
stamp(userstamp, flag)
browser.quit()
if __name__ == '__main__':
# driverpath = '..\chromedriver\chromedriver.exe' # chromedriver路径 windows下
driverpath = '/usr/chrome/chromedriver/chromedriver' # linux下
url = 'https://wfw.scu.edu.cn/ncov/wap/default/index' # 已经登录进去的界面地址
username = ['xxxxx', 'xxxxx'] # 用户名(学号)
password = ['xxxxx', 'xxxxx'] # 密码
latitude = 30.630869 # 虚拟位置纬度
longitude = 104.083748 # 经度
userstamp = ['xxxx@qq.com', 'xxxx@qq.com']
for i in range(2):
try:
browser = driver(driverpath)
except:
print('please update your browser driver')
clock(username=username[i], password=password[i], lat=latitude, long=longitude, url=url, userstamp=userstamp[i], browser=browser)
运行成功后打卡结果会发送到邮箱