ZJU打卡基于pyppeteer,tkinter

1. 思路介绍

思路简单,使用模拟浏览器自动登录,自动选择问卷,自动获取位置,最后提交。然后打包成.exe文件,最后用windows自动定时任务启动程序,技术比较简单

2. 依赖介绍

pyppeteer介绍
tkinter介绍

3. 优点

  • 只有一个exe文件
  • 第一次运行可以自动安装chromiu,不需要安装其他环境
  • 账号密码保存本地
  • 运行比较稳定

4.有待改进

  • 加上自动选择打卡地点,而不是通过浏览器H5位置接口获取
  • 打包成其他平台的可执行文件
  • 邮件提醒,现在只有截图弹窗提醒
  • 部署服务器上

4. 解决问题

(1)首次运行pyppeteer 下载chromium太慢卡死
更换淘宝源
(2)打包.exe文件出现相对路径不对的情况
在桌面打开终端当前路径是system32,不是desktop,所有路径问题需要解决
获取工作环境目录
(3)自动关闭弹窗
多线程自动执行主窗口关闭任务

5. 展示

6. 源码

# coding:utf-8
# -*- coding: utf-8 -*-
# @Time    : 2021/12/16 16:31
# @Author  : Junieson
# @File    : healthreporter.py
# @Software: PyCharm

import asyncio
import datetime
import os
import random
import sys
import threading
import time
import tkinter
from tkinter import Tk, Label, Entry, CENTER, Button
from tkinter import messagebox
from pyppeteer import launch
from faker import Factory
from PIL import Image, ImageTk

f = Factory.create()


class load:
    id = ''
    pw = ''
    # 是否可视化
    vis = 1
    def __init__(self):
        self.root = Tk()
        self.root.title("首次登录输入账号密码")
        self.root.geometry("300x150+600+300")
        # 设置用户账号输入框
        self.ID = Label(self.root, text="账号:")
        self.ID.place(relx=0.2, rely=0.2, anchor=CENTER)
        self.text1 = Entry(self.root)
        self.text1.place(relx=0.55, rely=0.2, anchor=CENTER, width=160, height=25)

        # 设置用户密码码输入框
        self.password = Label(self.root, text="密码:")
        self.password.place(relx=0.2, rely=0.4, anchor=CENTER)
        self.text2 = Entry(self.root)
        self.text2.place(relx=0.55, rely=0.4, anchor=CENTER, width=160, height=25)

        # 设置登录按钮
        self.enter = Button(self.root, text="登录", command=self.submit, width=15, height=1)
        self.enter.place(relx=0.55, rely=0.83, anchor=CENTER)

        # 是否可视化
        self.isvis = Label(self.root, text="可视化:")
        self.isvis.place(relx=0.22, rely=0.6, anchor=CENTER)
        self.r = tkinter.IntVar()
        self.r.set(1)
        self.male_select = tkinter.Radiobutton(self.root, text='是', value=1, variable=self.r, command=self.func)
        self.male_select.place(relx=0.45, rely=0.6, anchor=CENTER)
        self.female_select = tkinter.Radiobutton(self.root, text='否', value=0, variable=self.r, command=self.func)
        self.female_select.place(relx=0.7, rely=0.6, anchor=CENTER)

    # 定义选择后执行的函数
    def func(self):
        self.vis = self.r.get()

    def submit(self):
        self.id = self.text1.get()
        self.pw = self.text2.get()
        messagebox.showinfo('提示', '保存成功,修改在“user_info.text”文件!')
        self.root.quit()
        self.root.destroy()

    def show(self):
        self.root.mainloop()


async def main():
    # 创建浏览器对象
    id, pw, isvis = get_info()
    browser = await launch(headless=not bool(int(isvis)), args=['--disable-infobars', f'--window-size={415},{1050}'],
                           dumpio=True)
    # 打开新的标签页
    page = await browser.newPage()
    await page.evaluate('''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''')
    await page.evaluate('''() =>{ window.navigator.chrome = { runtime: {},  }; }''')
    await page.evaluate('''() =>{ Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] }); }''')
    await page.evaluate('''() =>{ Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5,6], }); }''')

    # 设置视图大小
    await page.setViewport({'width': 400, 'height': 1000})

    # 设置UserAgent
    await page.setUserAgent(f.user_agent())

    # 访问页面
    url = 'https://healthreport.zju.edu.cn/ncov/wap/default/index'
    response = await page.goto(url)
    await asyncio.sleep(2)
    print("打开页面...")
    # 登录
    # input_user = await page.xpath('//*[@id="username"]')
    # await input_user[0].type('22160170', {'delay': random.randint(100, 151) - 50})
    try:
        a = await page.xpath('//*[@id="username"]')
        if not a:
            while not await page.xpath('//*[@id="username"]'):
                page = await browser.newPage()
                await page.setViewport({'width': 400, 'height': 1000})
                await page.goto(url)
                print('请求非法')
    except:
        while not await page.xpath('//*[@id="username"]'):
            page = await browser.newPage()
            await page.setViewport({'width': 400, 'height': 1000})
            await page.goto(url)
            print('请求非法')

    await page.type('#username', id, {'delay': random.randint(10, 30)})
    await page.type('#password', pw, {'delay': random.randint(10, 30)})
    print("输入账号密码...")
    await page.click('#dl')
    await asyncio.sleep(3)
    try:
        x = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[4]/div/div/div[1]')
        if not x:
            root = Tk().withdraw()
            messagebox.showinfo('提示', '出错请可视化手动登录')
            while not await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[4]/div/div/div[1]'):
                pass
    except:
        root = Tk().withdraw()
        messagebox.showinfo('提示', '出错请可视化手动登录')
        while not await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[4]/div/div/div[1]'):
            pass
    print("登录中...")
    # 接种
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[4]/div/div/div[1]')
    await choice[0].click()
    # 不是不宜接种
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[5]/div/div/div[5]')
    await choice[0].click()
    # 当前已完成接种
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[6]/div/div/div[2]')
    await choice[0].click()
    # 不是未返校
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[7]/div/div/div[2]')
    await choice[0].click()
    # 不是未到岗
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[8]/div/div/div[2]')
    await choice[0].click()
    # 不是发热
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[9]/div/div/div[2]')
    await choice[0].click()
    # 不是隔离
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[10]/div/div/div[2]')
    await choice[0].click()
    # 不是居家
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[11]/div/div/div[2]')
    await choice[0].click()
    # 没值得注意
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[12]/div/div/div[2]')
    await choice[0].click()
    # 已经申请健康码
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[13]/div/div/div[1]')
    await choice[0].click()
    await asyncio.sleep(2)
    # 绿码
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[14]/div/div/div[1]')
    await choice[0].click()
    # 在校
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[15]/div/div/div[1]')
    await choice[0].click()
    # 所在地
    print("获取地理位置...")
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[16]/div/div/div[1]')
    await choice[0].click()
    # await page.evaluateOnNewDocument(
    #     '''() =>{ Object.defineProperties(p,{ accuracy:{ get: () => null } }) }''')
    await asyncio.sleep(2)
    # 获取地理位置
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[19]/div')
    await choice[0].click()
    time.sleep(2)
    # 无密接
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[22]/div/div/div[2]')
    await choice[0].click()
    # 承诺书
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[4]/ul/li[34]/div/div/div')
    await choice[0].click()
    # # 提交
    choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[5]/div')
    await choice[0].click()
    try:
        choice = await page.xpath('//*[@id="wapcf"]/div/div[2]/div[2]')
        await choice[0].click()
    except:
        pass
    while not await page.xpath('//*[@id="wapat"]'):
        choice = await page.xpath('/html/body/div[1]/div[1]/div/section/div[5]/div')
        await choice[0].click()

    print("打卡...")
    # 截图
    nowdir = os.path.dirname(os.path.realpath((sys.executable)))
    await page.screenshot({'path': nowdir + '/shortcut.png'})
    await browser.close()  # 关闭浏览器
    show_res()
    print('恭喜!打卡成功')
    sys.exit()


def stop(root, label, times):
    for i in range(10):
        label['text'] = "恭喜打卡成功\n" + times + '\n倒计时关闭' + str(10 - i) + '秒'
        time.sleep(1)
    root.quit()


def get_info():
    nowdir = os.path.dirname(os.path.realpath((sys.executable)))
    try:
        with open(nowdir + '/user_info.txt', 'r', encoding='utf-8') as f:
            user_name = f.readline().replace('\n', '')
            user_password = f.readline().replace('\n', '')
            isvis = f.readline().replace('\n', '')
            f.close()
    except:
        with open(nowdir + '/user_info.txt', 'w', encoding='utf-8') as f:
            window = load()
            window.show()
            user_name, user_password, isvis = window.id, window.pw, window.vis
            if isvis == 0:
                print('当前不可视的静默模式,修改值为1可见')
            f.write(user_name + '\n')
            f.write(user_password + '\n')
            f.write(str(isvis) + '\n')
            f.close()
    return user_name, user_password, isvis


def show_res():
    root = Tk()
    nowdir = os.path.dirname(os.path.realpath((sys.executable)))
    img_open = Image.open(nowdir + "/shortcut.png")
    img_png = ImageTk.PhotoImage(img_open)
    now_time = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    label_img = tkinter.Label(root, text="恭喜打卡成功\n" + now_time, font=("微软雅黑", 20), fg="green", image=img_png,
                              compound='center')
    label_img.pack()
    t = threading.Thread(target=stop, args=(root, label_img, now_time))
    t.start()
    root.mainloop()


# show_res()
asyncio.get_event_loop().run_until_complete(main())

7. 下载

百度云
链接:https://pan.baidu.com/s/1m__tYbrk-_OZ9aiedJDJgw
提取码:1k4o
csdn
https://download.csdn.net/download/i6223671/64780844

8.定时任务

win定时任务

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值