One click reminder and one click View of the list of non learners

This project is completed with python+selenium+ddddocr+email. Selenium is used because my technology is limited and I can't crack the js encryption of the login interface (in Shaanxi); Ddocr is an open source verification code recognition project on github, with a high recognition rate; Reminders are sent by email.

The reason for doing this project is that every week the League Secretary has to check who hasn't studied one by one, and then remind one by one. It's too hard, so I made this script to reduce the work of the League secretary.

At present, I have only realized in Shaanxi. Friends in other regions can refer to my implementation ideas and change them.

Finished products and use course in Shaanxi: One click reminder tool for Youth Learning - [ Shaanxi region ]_ Beep beep beep_ bilibili



1, Login + analysis module

1.selenium+webdriver configuration

2. Login + get token

3. Analyze the data through token

2, Verification code identification module

3, Mail sending module

4, Program entry module

V. log module

tips: a module is a file

1, Login + analysis module

1.selenium+webdriver configuration

For example, you have edge browser on your computer, and then go to selenium's official website to download the corresponding version of webdriver of edge browser.

After downloading, unzip the driver to the project directory, and then call it like this (I use this to facilitate packaging):

driver = webdriver.Edge(executable_path='msedgedriver.exe')

You can also configure environment variables. Please Baidu for details.

2. Login + get token

You can see my login() function

Here's an explanation of why you don't save the token, because the valid period of the Shaanxi website token is only 2 hours.

3. Analyze the data through token

You can see my getRequest() function

import requests
import json
from selenium import webdriver
import time
from LogSystem import writeLog
import base64
from io import BytesIO
from PIL import Image
import re
from OCR import ddocr

class qndxx:
    def __init__(self, account, passwd):
        self.account = account
        self.password = passwd
        self.token = ""

    def base64_to_image(self, base64_str):
        base64_data = re.sub('^data:image/.+;base64,', '', base64_str)
        byte_data = base64.b64decode(base64_data)
        image_data = BytesIO(byte_data)
        img =
        return img

    def login(self):
        # There is a token value in the successful cookie
        url = ""

            driver = webdriver.Edge(executable_path='msedgedriver.exe')
        except Exception:
            print("Please update Edge Browser to latest version-ver100")

        driver.implicitly_wait(3)  # Recessive waiting for 3s
        # tkinter.messagebox.showerror('prompt ',' just enter the verification code, do not click the login button on the web page ')
        while 1:

            driver.find_element("xpath", "//*[@id='pane-first']/div/div/form/div[1]/div/div/input").send_keys(
            driver.find_element("xpath", "//*[@id='pane-first']/div/div/form/div[2]/div/div/input").send_keys(
            ce = driver.find_element("xpath", "//*[@id='pane-first']/div/div/form/div[3]/div/img").get_attribute("src")

            img = self.base64_to_image(ce)

            verfCode = ddocr('code.png')
            # tkinter.messagebox.showerror('prompt ',' enter the verification code and then close the pop-up window ')

            driver.find_element("xpath", "//*[@id='pane-first']/div/div/form/div[3]/div/div/input").send_keys(
            driver.find_element("xpath", "//*[@id='pane-first']/div/div/form/button").click()

            cur_cookies = driver.get_cookies()

            if cur_cookies[0]["name"] == "token":

        # print(cur_cookies[0]["value"])
        self.token = cur_cookies[0]["value"]

        # with open("222222.txt", "w") as f:
        #     f.write(json.dumps(cur_cookies))

        return True

    def getRequest(self):
        list_meixue = []
        if self.login():
            head = {
                "token": self.token,
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68"

            url = ""
            url_qing = ""

            text_data = requests.get(url=url, headers=head).text
            data = json.loads(text_data)
            # print(data)
            for line in data['data']['data']:
                if line["isStudy"] == "no":
            text_data = requests.get(url=url_qing, headers=head).text
            data = json.loads(text_data)
            # print(data)
            for line in data['data']['data']:
                if line["isStudy"] == "no":

            if len(list_meixue) == 0:
                print("All the major studies of this period have been completed")
                line1 = "common%d I didn't study this period" % len(list_meixue)
                line2 = " ".join(list_meixue)
        return list_meixue

2, Verification code identification module

import ddddocr

def ddocr(file):
        ocr = ddddocr.DdddOcr()
        with open(file, 'rb') as f:
            img_bytes =
        res = ocr.classification(img_bytes)
        return res
        print("Failed to obtain verification code, please continue!")

3, Mail sending module

import smtplib
from email.mime.text import MIMEText
from email.header import Header

from email.mime.multipart import MIMEMultipart

def send_mail(accountList, eAccount, eAuthorizationCode, eTitle, eContent):
    msg_from = eAccount  # Sender email
    passwd = eAuthorizationCode  # It's the authorization code above
    to_addr = accountList  # Recipient email, list
    # print(to)

    # Set message content
    # The MIMEMultipart class can put anything
    msg = MIMEMultipart()
    content = eContent
    # Add content
    msg.attach(MIMEText(content, 'plain', 'utf-8'))

    # Set message subject
    msg['Subject'] = eTitle

    # Set sender information
    msg['From'] = 'Youth Learning reminder Bot'
    # Set recipient information
    msg['To'] = 'Students without youth study'

    # Start sending
        temp_flag_email = msg_from.split("@")[-1]
        if temp_flag_email == "":
            # Send via SSL, server address and port
            s = smtplib.SMTP_SSL("", 465)
        elif temp_flag_email == "":
            s = smtplib.SMTP_SSL("", 465)
        elif temp_flag_email == "":
            s = smtplib.SMTP_SSL("", 465)
        elif temp_flag_email == "":
            s = smtplib.SMTP_SSL("", 465)
            # If there is no match, QQ email will be used by default
            s = smtplib.SMTP_SSL("", 465)
        # Login mailbox
        s.login(msg_from, passwd)
        # Start sending
        res = s.sendmail(msg_from, to_addr, msg.as_string())
        if len(res) != 0:
            print("Sending failed, error code:", res)
        print("Mail sent successfully")
    except smtplib.SMTPException as e:
        print("Mail sending failed!!", e)

4, Program entry module

Read the configuration from the config file before starting the program

import configparser
import os

from qndxx import qndxx
from send_emile import send_mail

# Configuration initialization
cf = configparser.ConfigParser()"config.ini", encoding="utf8")
account = cf.get("accountPart", "account")
password = cf.get("accountPart", "password")
eAccount = cf.get("sendEmail", "eAccount")
eAuthorizationCode = cf.get("sendEmail", "eAuthorizationCode")
eTitle = cf.get("emailContent", "eTitle")
eContent = cf.get("emailContent", "eContent")

print("Configuration initialization--complete")
print("Please check before use config Is the file configured correctly")

# print("mail sending test mode, recipient: ")

# print("click the OK button in the pop-up window, and the program will continue to run")
qn = qndxx(account, password)
list_meixue = qn.getRequest()
list_email = []
if input("Send reminder email(1 Send, 0 don't send): ") == "1":
    for line in list_meixue:
            email = cf.get("emailList", line)
        except Exception:
            print(line + "\t Mailbox not initialized")

    if len(list_meixue) == len(list_email):
        send_mail(list_email, eAccount, eAuthorizationCode, eTitle, eContent)
        print("Please in config File initializes everyone's mailbox before running")


 config.ini file configuration

; Fill in the account and password of Shaanxi Youth big data service platform,

; To fill in your own email account, you need to open SMTP service
; Authorization code

; Fill in the name and email address of class members. There can be no blank space. If it is not filled in, you can only use the function of viewing the list of students who have not studied
Zhang San=
Li Si=

; Fill in the header and content of the message, and no line breaks are allowed
eTitle = please learn youth learning now!!
eContent = please learn youth learning now!! -- xxx remind Bot

V. log module

import time

# LogText: data to be recorded
def writeLog(LogText=''):
    # Formatted as 2021-08-05 09:42:08
    time_true = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    filename = "./Log.txt"
    with open(filename, 'a+', encoding="utf8") as f:
        f.writelines([time_true, "\t", LogText + "\n"])

Finally, if you need specific explanation (solution ideas of each part + packaging tutorial), you can leave a message. If you need more, I will issue a detailed article to explain.

Tags: Python

Posted by Fyorl on Sun, 17 Apr 2022 13:07:42 +0930