Автоматическая передача данных о температуре тела в температурную систему школы
Мотивация
Поскольку случилась пандемия Covid-19, в моей школе требовалось, чтобы каждый ученик сообщал температуру тела в систему отчетности о температуре в период с шести утра до восьми утра каждый божий день, чтобы избежать распространения болезни/вируса. Я считаю эту политику действительно ненужной и бесполезной. Потому что реальную температуру тела никто не сообщит, вместо этого она приносит неприятности каждому студенту, потому что все ленивы, в том числе и я. Важно то, что если вы забудете сообщить температуру, то получите предупреждение.
Я абсолютно не приемлю это хлопотное требование. Поэтому я решаю написать веб-краулер, который будет автоматически сообщать о температуре тела.
В начале это было очень успешно; Я использую веб-краулер, чтобы сообщать о температуре. Я использовал его, чтобы сообщить свою температуру, как обычно, поэтому я обнаружил, что он не может успешно сообщать о температуре, он может сообщать только вручную. Я увидел интерфейс, который меня действительно ошеломил, когда я открыл веб-сайт.
Честно говоря, я немного удивлен и ошарашен одновременно, когда увидел этот интерфейс, поэтому начал думать над решением.
Начать делать
Идеи 1
язык разработки: python
с помощью пакета расширения:
import requests from bs4 import BeautifulSoup, element from selenium import webdriver import selenium import time
сначала я использую requests
для обхода веб-сайта, а затем помещаю его в BeautifulSoup
для анализа.
url='https://webap1.kshs.kh.edu.tw/kshsSSO/publicWebAP/bodyTemp/index.aspx' r=requests.get(url) soup=BeautifulSoup(r.text,'lxml')
Теперь я просканировал веб-сайт, и теперь моя миссия состоит в том, чтобы позволить компьютеру проверить правильный вариант.
Подход, при котором могут возникнуть проблемы с получением проверочного номера.
веб-сайт после вскрытия BeautifulSoup, затем используйте подход find$=(id=’ContentPlaceHolder1_lb’)
, чтобы найти область проверочного номера из HTML, и сохраните tag_verification_num.string
(проверочный номер) в переменной tag_verification_num. Но теперь возникает проблема, когда я печатаю переменную tag_verification_num, значение нулевой.
Решение
После анализа веб-сайта через beautifulsoup используйте подход find$=(id=’ContentPlaceHolder1_lb’)
, чтобы найти область отображения проверочного номера, и после сохранения ag_verification_num.string(проверочный номер) в переменную tag_verification_num, тип перехода в строку, затем я нахожу этот тип перехода метки диапазона в строка, 65-й символ которой является проверочным номером.
Затем я сохраняю его в переменных для последующего использования.
tag_verification_num=soup.find(id='ContentPlaceHolder1_lbN') num_verification=str(tag_verification_num) num_verification=num_verification[65]
Теперь я получил проверочный номер, затем мне нужно получить номера каждого варианта проверки.
HTML-структура параметра проверки использовала метку диапазона для переноса параметра ввода и метки номера отображаемого параметра.
Итак, я использую подход find.(id=’ContentPlaceHolder1_RadioButtonList1')
, чтобы найти входную метку и ее родительский диапазон, затем сохраняю ее в переменную tag_verification, а затем использую подход tag_verification.find_all(‘input’)
, чтобы найти все входные метки в диапазоне.
tag_verification=soup.find(id='ContentPlaceHolder1_RadioButtonList1') tag_verification_input=tag_verification.find_all('input')
Неверный подход к получению значения параметра
После того, как вы прошли подход tag_verification.find_all(‘input’)
, чтобы получить все метки ввода в метке диапазона, затем используйте цикл for i in tag_verification_input:
для доступа к значению каждой метки ввода, но у меня есть проблема, вероятно, выше этого момента, которая отображает ноль, когда я печатаю переменную i.
Решение
здесь также можно использовать то же решение, что и выше, преобразовать тип входной метки в строку, а найти значение — это первые несколько символов в строке, чтобы я мог получить номера вариантов проверки.
tag_verification=soup.find(id='ContentPlaceHolder1_RadioButtonList1') tag_verification_input=tag_verification.find_all('input') for i in tag_verification_input: num_input=str(i) num_input[121]//驗證選項的數字
Поскольку метка ввода в переменной tag_verification_input заменяется переменной i в цикле for, поэтому переменная i заменит параметр проверки ниже.
Теперь я получил проверочный номер, а также получил номер каждой опции, следующим шагом я хочу сделать программирование, чтобы определить, какое количество опций равно проверочному номеру.
Я добавил условные выражения в цикл for i in tag_verification_input:
, чтобы определить, равен ли 121-й символ переменной char, которую я трансформирую в строку, переменной num_verification
.
for i in tag_verification_input: num_input=str(i) if num_verification==num_input[121]: //填報體溫
Я уже знаю входную метку, которая соответствует проверочному номеру, теперь мне нужно знать атрибут этой входной метки, чтобы я мог использовать подход find_element_by_name()
для управления веб-драйвером, чтобы проверить правильный вариант. если использовать подход большинства интуиций num_input=i.name
, значение переменной num_input равно нулю, как и выше. Поэтому также необходимо преобразовать тип переменной i в строку, а затем num_input[57:99]
сохранит символы в диапазоне от 59-го до 99-го, что является именем переменной i .
После того, как я получил имя метки ввода, я могу управлять веб-драйвером, чтобы проверить правильный вариант.
import requests
from bs4 import BeautifulSoup, element
from requests.models import Response
from selenium import webdriver
import selenium
import time
url='https://webap1.kshs.kh.edu.tw/kshsSSO/publicWebAP/bodyTemp/index.aspx'
r=requests.get(url)
soup=BeautifulSoup(r.text,'lxml')
driver=webdriver.Chrome("./chromedriver")
driver.get(url)
tag_verification_num=soup.find(id='ContentPlaceHolder1_lbN')
num_verification=str(tag_verification_num)
num_verification=num_verification[65]
def enter_step1():
tag_input = driver.find_element_by_name("ctl00$ContentPlaceHolder1$txtId")
tag_input.send_keys('(身分證字號)')
driver.find_element_by_name("ctl00$ContentPlaceHolder1$btnId").click()
def enter_step2():
driver.find_element_by_name('ctl00$ContentPlaceHolder1$rbType').click()
driver.find_elenent_by_xpath('//*[@id="ContentPlaceHolder1_ddl1"]/option[3]').click()
driver.find_element_by_xpath('//*[@id="ContentPlaceHolder1_ddl2"]/option[3]').click()
driver.find_element_by_xpath('//*[@id="ContentPlaceHolder1_ddl3"]/option[2]').click()
driver.find_element_by_name('ctl00$ContentPlaceHolder1$btnId0').click()
tag_verification=soup.find(id='ContentPlaceHolder1_RadioButtonList1')
tag_verification_input=tag_verification.find_all('input')
for i in tag_verification_input:
num_input=str(i)
print('迴圈外',num_input[121])
if num_verification==num_input[121]:
print('要驗證的數字',num_verification)
print('要輸入的數字',num_input[121])
print('secess\n')
print(i)
print(type(i),'\n')
print(num_input[57:99])
print(type(num_input[57:99]))
print('選取的數字:',num_input[121])
driver.find_element_by_name(num_input[57:99]).click()
enter_step1()
enter_step2()
else:
print('fail')
time.sleep(3)
driver.quit()
Улучшать
Мотив 2.0
2021/4/21 Менеджер школьного веб-сайта снова обновил систему отчетов о температуре тела.
Функция проверки меняется, чтобы ответить на непредсказуемый вопрос, это обновление снова меня удивляет. Кстати, я предлагаю в следующий раз обновить функцию проверки, чтобы решить исчисление.
Идея 2.0
причудливый
Моя первоначальная идея состоит в том, что менеджер школьного веб-сайта задаст вопрос о базовых знаниях, как все знают, поэтому я планирую использовать запросы функций и BeautifulSoup, чтобы получить вопрос, а затем через Википедию найти правильный ответ, наконец, определить, являются ли оба ответы из Википедии и системы проверки совпадают.
проблема: после изменения подхода к проверке я обнаружил, что requests
и beautifulsoup
бесполезны для анализа любого атрибута ярлыка.
Решение: нет возможности — нет решения.
исчерпывающее решение
впоследствии я изобретаю подход, который позволяет игнорировать любое значение метки и контрольных вопросов. Это весь атрибут id входной метки, передняя часть строки которого равна ContentPlaceHolder1_RadioButtonList1_
, а последнее число — это вариант буфера, например:
первый вариант:ContentPlaceHolder1_RadioButtonList1_0
второй вариант:ContentPlaceHolder1_RadioButtonList1_1
третий вариант:ContentPlaceHolder1_RadioButtonList1_2
Затем я могу следовать правилам, чтобы попробовать каждый вариант, чтобы решить эту проблему.
Функция
Для удобства я бы поставил функцию представлять любую операцию, кроме проверки.
enter_step1()
Функция: введите идентификатор удостоверения и нажмите кнопку отправки.
def enter_step1():
print('step1')
driver.find_element_by_id('ContentPlaceHolder1_txtId').
send_keys('(身分證字號)')
driver.find_element_by_id('ContentPlaceHolder1_btnId').click(
2. enter_step2()
функция:заполнение температуры теласостояние и статус посещаемости
def enter_step2():
print('step2')
driver.find_element_by_id('ContentPlaceHolder1_rbType_1').click()
driver.find_element_by_xpath('//*[@id="ContentPlaceHolder1_ddl1"]/option[3]').click()
driver.find_element_by_xpath('//*[@id="ContentPlaceHolder1_ddl2"]/option[4]').click()
driver.find_element_by_xpath('//*[@id="ContentPlaceHolder1_ddl3"]/option[2]').click()
3. submit()
функция: нажмите кнопку завершения заполнения.
def sunmit(): print('submit') driver.find_element_by_id('ContentPlaceHolder1_btnId0').click()
подтверждение
Во-первых, удалите все последние числа, представляющие номер опции, из строки атрибута id и сохраните эту строку в переменной id
.
id='ContentPlaceHolder1_RadioButtonList1_'
Потому что количество опционов будет меняться каждый день, но по моим наблюдениям до четырех. Поэтому я использую цикл for i in range(3)
и объявил переменную, равную name+str(i)
, которая может через цикл for получить каждое атрибут переменной i входной метки, а затем поместить эту переменную в функцию find_element_by_id()
, пробовать каждый круг. Поскольку, если проверка не пройдена, прогресс продолжает сообщать о температуре тела, он получит ошибку, поэтому я должен установить обработку исключений в цикле for, если проверка не удалась, то прогресс переходит к следующему кругу.
После нажатия кнопки начала заполнения веб-сайт отобразит предупреждающее сообщение, поэтому я использую function switch_to_alert().accept()
для подтверждения этого предупреждающего сообщения.
for i in range(3):
try:
input_id=name+str(i)
print(input_id)
driver.find_element_by_id(input_name).click()
enter_step1()
driver.switch_to_alert().accept()
print('success')
enter_step2()
# sunmit()
except:
print('fail')
# driver.switch_to_alert().accept(
завершение
независимо от различных проблем с проверкой, также не может повлиять на реализацию программирования.
Код
import requests from selenium import webdriver import time
url='https://webap1.kshs.kh.edu.tw/kshsSSO/publicWebAP/bodyTemp/index.aspx' driver=webdriver.Chrome("./chromedriver") driver.get(url)
def enter_step1(): print('step1') driver.find_element_by_id('ContentPlaceHolder1_txtId').send_keys('(身分證字號)') driver.find_element_by_id('ContentPlaceHolder1_btnId').click() def enter_step2(): print('step2') driver.find_element_by_id('ContentPlaceHolder1_rbType_1').click() driver.find_element_by_xpath('//[@id="ContentPlaceHolder1_ddl1"]/option[3]').click() driver.find_element_by_xpath('//[@id="ContentPlaceHolder1_ddl2"]/option[4]').click() driver.find_element_by_xpath('//[@id="ContentPlaceHolder1_ddl3"]/option[2]').click() def sunmit(): print('submit') driver.find_element_by_id('ContentPlaceHolder1_btnId0').click()
id='ContentPlaceHolder1_RadioButtonList1_' for i in range(3): try: input_id=name+str(i) print(input_id) driver.find_element_by_id(input_name).click() enter_step1() driver.switch_to_alert().accept() print('success') enter_step2() sunmit() except: print('fail') time.sleep(5) driver.quit()