每日自動健康打卡(Python+騰訊雲伺服器)
每日自動健康打卡(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.參考鏈接
騰訊雲伺服器上運行(免費1個月)選擇輕量應用伺服器,我選的linux系統,這裡的實例也是linux
4.linux伺服器配置
1.以root登錄
2.下載Python3.7,升級pip,yum,更換中國源
3.安裝庫,執行以下命令
pip3 install selenium
pip3 install pillow
pip3 install baidu-aip
4.在linux上安裝Google瀏覽器和驅動
在目錄 /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=//dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=//dl-ssl.google.com/linux/linux_signing_key.pub
具體操作:按i插入,按Esc,然後Shift+;,輸入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 //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 = '//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),需要自行註冊,不會的可以參考這篇部落格://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": "//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 = '[email protected]' # 發件人郵箱帳號
my_pass = 'XXX' # 發件人郵箱密碼(當時申請smtp給的口令)
my_user = '[email protected]' # 收件人郵箱帳號
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()
運行結果圖: