• 1

  • 467

  • 收藏

linux上实现每日自动打卡并邮件通知

智能的司机

我是老司机

2个月前

tags: python,selenium,linux

背景

学校放寒假了,又恢复了去年在家每天打卡的日常,今年就想研究一下怎么用python自动打卡并且放在linux服务器上定时运行,今天就分享一下我的实现方法。

bnuz打卡的网页地址: http://xgfx.bnuz.edu.cn/xsdtfw/sys/emapfunauth/pages/welcome.do?service=%2Fxsdtfw%2Fsys%2Fswmxsyqxxsjapp%2F*default%2Findex.do%3FwxType%3D1

环境准备

  • 谷歌浏览器

  • 安装:

    yum install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
    复制代码
  • 查看谷歌版本号

    google-chrome -version
    复制代码
  • 下载对应版本谷歌浏览器驱动:

  • 淘宝镜像地址:http://npm.taobao.org/mirrors/chromedriver

  • 选择对应的版本号后wget下载

    wget https://cdn.npm.taobao.org/dist/chromedriver/88.0.4324.96/chromedriver_linux64.zip
    复制代码
    • 下载完成后,解压,移动到/usr/bin下
    unzip chromedriver_linux64.zip
    mv chromedriver /usr/bin/
    复制代码
    • 查看chromedriver版本号 chromedriver --version

注意:驱动的版本号要和浏览器的版本号一致 (若使用别的浏览器则下载该浏览器的驱动)

  1. 下载selenium
    pip install selenium
    复制代码

使用selenium结合XPATH操作元素

  • 使用selenuim模拟点击、输入、清空等事件。
  • 使用XPATH定位元素
    • 如何确定XPATH?

可以自己通过dom确定,也可以使用谷歌浏览器自带的功能快速定位。

使用谷歌浏览器快速得到XPATH优缺点

优点

方便快捷,小白也能轻松上手

缺点

①当页面元素会随着操作变化时,使用XPATH绝对定位可能会定位失败

②当页面有嵌套子页面的时候使用XPATH绝对定位会失败 但是selenuim可以通过多种方式定位元素,当无法使用XPATH的时候可以通过别的办法进行定位。

  • 谷歌快速得到 full XPATH的方法

F12打开开发者模式

实现代码

特别提醒:本代码仅用于自学,禁止商用!如身体健康出现异常请及时停用自觉向学校报备!本人概不负责。

#Language:Python
#Author: Lily
#Date:2021/1/20

#注:本代码是基于用户之前已经手动提交过“每日报平安”的基础上的,
#因为服务器会保存用户的重要信息,如:家庭住址,所在地区等,
#所以这篇代码就可不必填这些敏感信息。

#特别提醒:本代码仅用于自学,禁止商用!如身体健康出现异常请及时停用自觉向学校报备!本人概不负责。

from selenium import webdriver
from time import sleep
from email.header import Header
from smtplib import SMTP_SSL
import datetime
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from selenium.webdriver.chrome.options import Options

# 发邮件 msg_to:接收者邮箱
def send(msg_to):
	# 我用的是MIMEMultipart的模式,所以可以在邮件里夹图片。
    subject = "python+linux测试"  # 主题
    msg = MIMEMultipart('related')
    content = MIMEText('<html><body><h2>测试linux打卡。</h2></body></html>', 'html', 'utf-8')  # 正文
    # msg = MIMEText(content)
    msg.attach(content)
    msg['Subject'] = subject
	# 发送者邮箱
    msg['From'] = "869@qq.com"
    msg['To'] = msg_to
    try:
        s = smtplib.SMTP_SSL("smtp.qq.com", 465) # 邮件服务器及端口号
        s.login("869@qq.com", "xxxxxxxxxxxxxxxx")  # xxxxx是邮箱的校验码,不是邮箱密码,需在qq邮箱网页内自行获取。
        s.sendmail("869@qq.com", msg_to, msg.as_string())
        print("发送成功")
    except:
        print("发送失败")
    finally:
        s.quit()

# 用户类,保存用户在打卡页面的账号和密码,及通知邮箱地址。
class Person:
    schoolNum="180xxxxxx"
    psw="iampassword"
    email="123456@163.com"
    def __init__(self,schoolNum,psw,email):
        self.schoolNum = schoolNum
        self.psw = psw
        self.email = email
		
# 新建person数组存放Person对象
person=[]
person.append(Person('schoolnumber','thisispassword','herMailAddress@qq.com'))
person.append(Person('schoolnumber','password','hisMailAddress@163.com'))

# 遍历所有用户,模拟打卡操作
for per in person:
	# 因为在linux命令行里运行,所以设置无头模式在后台运行。
    chrome_options = Options()
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-dev-shm-usage')
    chrome_options.add_argument('--headless')
    # 模拟iPhone 6,因为这个页面如果不是手机端进入的话会进入管理端。
    chrome_options.add_argument('user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"')
    #创建对象
    driver = webdriver.Chrome(options=chrome_options)
    sleep(10)
    #进入网站 这里填打卡网站
    driver.get(
        'http://xgfx.bnuz.edu.cn/xsdtfw/sys/emapfunauth/pages/welcome.do?service=%2Fxsdtfw%2Fsys%2Fswmxsyqxxsjapp%2F*default%2Findex.do%3FwxType%3D1')
    # #登录
	# 我写了很多sleep,主要是防止网速太慢的时候,dom还没来得及渲染时,selenuim去进行点击等操作的时候会找不到目标元素,就会抛出错误。
    sleep(10)
    # 点击db认证
    driver.find_element_by_xpath('/html/body/div/div/div/div/div/button[2]').click()

    sleep(10)
    # 这里填账号
    driver.find_elements_by_xpath('//input[@class="ivu-input ivu-input-large ivu-input-with-prefix"]')[0].send_keys(
        per.schoolNum)  # 这里填密码
    driver.find_elements_by_xpath('//input[@class="ivu-input ivu-input-large ivu-input-with-prefix"]')[1].send_keys(
        per.psw)
    # 点击登陆
    driver.find_element_by_xpath('//button[@class="ivu-btn ivu-btn-primary ivu-btn-long ivu-btn-large"]').click()
    # 点击每日报平安
    sleep(10)
    driver.find_element_by_xpath('//*[@id="app"]/div/div[2]/a[2]').click()

    sleep(10)
    # 点击输入体温
    driver.find_element_by_xpath(
        '//*[@id="app"]/div/div[5]/div/div/div/div/div[7]/div/a/div[2]/div[2]/input').send_keys("37")
    sleep(10)
    # 点击目前详细地址 有session不用填
    # driver.find_element_by_xpath('//*[@id="app"]/div/div[5]/div/div/div/div/div[9]/div/a/div[2]/div[2]/div[1]/textarea').send_keys("金凤路18号")

    # 点击本人是否不适
    driver.find_element_by_xpath('//*[@id="app"]/div/div[5]/div/div/div/div/div[10]/div/a').click()
    sleep(10)
    # 点击否
    driver.find_element_by_xpath(
        '//*[@id="app"]/div/div[5]/div/div/div/div/div[10]/div/div/div[1]/div/div/div/a[2]/div[2]/div[1]/label/span[2]').click()

    # 点击本人家属是否接触史
    driver.find_element_by_xpath('//*[@id="app"]/div/div[5]/div/div/div/div/div[12]/div/a').click()
    sleep(10)
    # 点击否
    driver.find_element_by_xpath(
        '//*[@id="app"]/div/div[5]/div/div/div/div/div[12]/div/div/div[1]/div/div/div/a[2]/div[2]/div[1]/label').click()

    # 点击本人家属是否疑似接触过
    driver.find_element_by_xpath('//*[@id="app"]/div/div[5]/div/div/div/div/div[14]/div/a').click()
    sleep(10)
    # 点击否
    driver.find_element_by_xpath(
        '//*[@id="app"]/div/div[5]/div/div/div/div/div[14]/div/div/div[1]/div/div/div/a[2]/div[2]/div[1]/label').click()

    # 点击本人家属是不是疑似病例
    driver.find_element_by_xpath('//*[@id="app"]/div/div[5]/div/div/div/div/div[16]/div/a').click()
    sleep(10)
    # 点击否
    driver.find_element_by_xpath(
        '//*[@id="app"]/div/div[5]/div/div/div/div/div[16]/div/div/div[1]/div/div/div/a[2]/div[2]/div[1]/label').click()

    # 点击本人家属是否被隔离
    driver.find_element_by_xpath('//*[@id="app"]/div/div[5]/div/div/div/div/div[18]/div/a').click()
    sleep(1)
    # 点击否
    driver.find_element_by_xpath(
        '//*[@id="app"]/div/div[5]/div/div/div/div/div[18]/div/div/div[1]/div/div/div/a[2]/div[2]/div[1]/label').click()
    sleep(1)

    # 点击提交
    driver.find_element_by_xpath('//*[@id="app"]/div/div[6]/div/button').click()
    sleep(10)
    # 确认一下提交成功没有
    # 截图可以放进邮件里
    # driver.save_screenshot('./ch.png')
    
    #发送邮件通知
    send(per.email)
    driver.quit()

复制代码

linux布置定时任务

代码完成后就可以在服务器上布置定时任务定时运行了。这里用到的是crontab。 假设代码名称:python_bnuz.py,地址: /root/ 命令行输入:vim /etc/crontab

我设定的规则是每日0:10执行语句:

 python /root/python_bnuz.py
复制代码

结果展示

打卡状态通知:

如果没收到邮件的话即是没有打卡成功。 这个时候你可以查看crontab的日志看看是否正常执行。 查看crontab日志语句:tail -f /var/log/cron

结语

感谢你能看到这里呀。这次实践非常有趣,我也学习了很多之前没接触到的新知识。打代码的快乐就在于学后能应用于实际场景吧。自动打卡替我省去了很多麻烦,希望这篇文章也能帮助到你。

免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。

467

相关文章推荐

未登录头像

暂无评论