应用div模拟prompt存在的未能解决的问题

本文探讨了在JavaScript中使用div模拟alert(), prompt()等模态对话框的需求,重点在于如何模拟多线程中的Sleep函数。由于JavaScript的单线程特性,模拟sleep()函数成为难点,它需要在不阻塞页面的情况下等待用户输入。作者尝试创建一个myPrompt.show()函数,但在等待用户点击确定按钮时遇到问题,提出了通过循环检测变量来实现,但这样可能导致页面假死。文中分享了一段未解决问题的模拟prompt代码,并呼吁社区共同寻找解决方案。" 78270322,5694531,Python中判断变量类型的常用方法,"['Python编程', '数据类型', '编程基础']
部署运行你感兴趣的模型镜像

javascript中有几个模态阻塞对话框需要模拟分别是:


alert()
prompt()
confirm()
showModalDialog()


这些对话框的共同特点都是执行代码后,包含该代码的代码段都要停止或者说阻塞,等操作返回时,被阻塞的代码继续执行,类似断点。
通常,我们只所以要进行模拟,目的在于改善用户界面体验,或者说我们不想使用ie提供的那种默认的对话框样式,所以,我们想使用div层来进行模拟。
而模拟的难点其实在于如何实现一个类似于其他多线程编程语言中提供的Sleep()函数,但是,javascript是单线程执行的,这一点很可能不久的将来会得到改变,比如,以后很可能会支持如下的javascript脚本

function getValue()
{
   
while( document.getElementById("name").value == "" )
   
{
        window.sleep(
100);//#####将来或许能支持,当前尚不支持该函数
   }

   
return document.getElementById("name").value
}

 

这段代码虽然很简单,但是,我认为,如果能实现该功能了,那么,对上面提到的模拟工作就没有问题的了。其实,我们真正需要的是一个能够使线程进入休眠状态从而让出时间片的sleep()函数,为什么这样说,如果上面的函数写成了像下面的样子,尽管功能是相同的,但是,确会使得程序进入死循环而造成页面假死状态

function getValue()
{
    
while(document.getElementById("name").value=="")
    
{
    }

    
return document.getElementById("name").value;
}


因此,能否利用现有的javascript技术来模拟sleep()应该是该问题的一个核心所在。比如说我们试图写如下的代码段

var name = myPrompt.show("请输入姓名:");
alert(name);


我们的目的是希望我们自己的myPrompt.show()函数创建一个div层来模拟prompt(),这点不难做到,继续下去,在myPrompt.show()里面创建一个div层之后,就需要等待用户输入并点击确定按钮了,确定后,提取用户输入内容作为myPrompt.show()的返回值,问题就在于,我们如何在myPrompt.show()函数中创建一个div层后等待用户的输入,直到用户输入并点击确定按钮后,再继续执行myPrompt.show()函数后面的代码,我们最容易想到的解决办法就是执行一个循环语句,循环检测某个变量是否被赋值(该变量是在用户点击确定按钮时赋值的),如果还没有被赋值,那么,继续等,如果赋值则结束循环,代码继续。如何实现这个,回到了前面讨论的那个getValue()的实现上了,要循环检测但又不造成假死,只有实现sleep()的功能。

我为了做测试,实现了一个模拟prompt的代码,但是!!!!上面提到的问题没有解决!!!!把代码贴出来,希望和兄弟们一起讨论解决之道。

注意:this.waitForUserInput();就是我无法实现的一个函数,也就是模拟sleep()功能

AjaxPrompt = 
{
 div_handle:
null,
 msk_handle:
null,
 div_value:
null,
 timer_name:
null,
 show:
function()
 
{
  
this.showMaskPage();
  
this.showMyPrompt();
  
this.waitForUserInput();
  
this.hideMaskPage();
  
return this.div_value; 
 }
,
 showMaskPage : 
function()
 
{
  
this.msk_handle = document.createElement("<div style="z-index:1000;position:absolute;top:0;left:0;width:"+document.body.clientWidth+";height:"+document.body.clientHeight+""></div>");
  document.body.appendChild(
this.msk_handle);
  
this.msk_handle.innerHTML = "<iframe style="FILTER:Alpha(opacity=20);width:100%;height:100%"></iframe>";
 }
,
 hideMaskPage : 
function()
 
{
  
if(this.msk_handle!=null)
  
{
   document.body.removeChild(
this.msk_handle);
   
this.msk_handle = null;
  }

 }
,
 showMyPrompt : 
function()
 
{
  
this.div_handle= document.createElement("<div style=z-index:1001;position:absolute;top:200;left:300;width:100;height:50;background-color:#cccccc></div>");
  
this.div_handle.innerHTML = "<input id=myprompt_userinput value=请您输入数据><input id=myprompt_button type=button value=确定>";
  document.body.appendChild(
this.div_handle);
  document.getElementById(
"myprompt_button").onclick = this.setUserInput;
 }
,
 setUserInput : 
function()
 

  AjaxPrompt.div_value 
= document.getElementById("myprompt_userinput").value;
  document.body.removeChild(AjaxPrompt.div_handle);
 }
,
 waitForUserInput : 
function()
 
{
  
//这里需要实现类似sleep()的功能
 }

}


代码希望如下调用

function test()
{
    
var name = AjaxPrompt.show();
    alert(name);
}


但是,由于this.waitForUserInput();没有能够实现预想的效果,因此,运行后,alert出来的始终是null
 

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>点餐系统</title> <style> body { font-family: Arial, sans-serif; background-color: #f4f4f9; margin: 0; padding: 20px; } .container { width: 80%; margin: auto; background-color: white; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } h1 { text-align: center; } .menu-section, .cart-section, .admin-section, .membership-section { display: flex; justify-content: space-between; margin-bottom: 20px; } .menu-item, .cart-item, .admin-item, .membership-item { width: 45%; background-color: white; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } .menu-item button, .cart-item button, .admin-item button, .membership-item button { padding: 5px 10px; background-color: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer; } .menu-item button:hover, .cart-item button:hover, .admin-item button:hover, .membership-item button:hover { background-color: #0056b3; } table { width: 100%; border-collapse: collapse; } th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; } th { background-color: #f2f2f2; } tr:hover { background-color: #f1f1f1; } .total { margin-top: 20px; font-size: 18px; font-weight: bold; } .checkout-section { margin-top: 20px; } .checkout-section input[type="number"] { width: 100px; padding: 5px; border: 1px solid #ccc; border-radius: 5px; margin-right: 10px; } .checkout-section button { padding: 5px 10px; background-color: #28a745; color: white; border: none; border-radius: 5px; cursor: pointer; } .checkout-section button:hover { background-color: #218838; } .admin-form input[type="text"], .admin-form input[type="number"] { width: 100%; padding: 10px; margin-bottom: 10px; border: 1px solid #ccc; border-radius: 5px; } .membership-form input[type="number"] { width: 100%; padding: 10px; margin-bottom: 10px; border: 1px solid #ccc; border-radius: 5px; } .membership-status { margin-top: 10px; font-size: 16px; font-weight: bold; } .receipt-modal { display: none; position: fixed; z-index: 1; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4); } .receipt-modal-content { background-color: #fefefe; margin: 15% auto; padding: 20px; border: 1px solid #888; width: 50%; } .close-button { color: #aaa; float: right; font-size: 28px; font-weight: bold; } .close-button:hover, .close-button:focus { color: black; text-decoration: none; cursor: pointer; } </style> </head> <body> <div class="container"> <h1>点餐系统</h1> <div class="membership-status" id="membership-status">当前状态: 非会员</div> <div class="menu-section"> <div class="menu-item"> <h2>菜单</h2> <table id="menu-table"> <thead> <tr> <th>菜品名称</th> <th>价格</th> <th>状态</th> <th>操作</th> </tr> </thead> <tbody id="menu-items"> <!-- 菜品项将动态生成 --> </tbody> </table> </div> <div class="cart-item"> <h2>购物车</h2> <table> <thead> <tr> <th>菜品名称</th> <th>数量</th> <th>单价</th> <th>总价</th> <th>会员价</th> <th>操作</th> </tr> </thead> <tbody id="cart-items"></tbody> </table> <div class="total" id="total-price">总价: ¥0.00</div> <div class="total" id="member-price">会员价: ¥0.00</div> <div class="checkout-section"> <button onclick="checkout()">结算</button> <button onclick="printReceipt()">打印小票</button> </div> </div> </div> <div class="admin-section"> <div class="admin-item"> <h2>管理员操作</h2> <form class="admin-form"> <input type="text" id="new-dish-name" placeholder="菜品名称" required> <input type="number" id="new-dish-price" placeholder="价格" min="0" step="any" required> <button type="button" onclick="addDish()">上架菜品</button> </form> <button onclick="toggleAdminForm()">修改菜品信息</button> <div id="modify-dish-form" style="display: none;"> <select id="dish-to-modify" onchange="loadDishInfo()"> <option value="">选择菜品</option> <!-- 菜品选项将动态生成 --> </select> <input type="text" id="modified-dish-name" placeholder="新的菜品名称" required> <input type="number" id="modified-dish-price" placeholder="新的价格" min="0" step="any" required> <button type="button" onclick="updateDish()">保存修改</button> </div> </div> </div> <div class="membership-section"> <div class="membership-item"> <h2>会员充值</h2> <form class="membership-form"> <input type="number" id="recharge-amount" placeholder="充值金额" min="0" step="any" required> <button type="button" onclick="recharge()">充值</button> </form> <div class="total" id="balance">余额: ¥0.00</div> <button onclick="toggleMembership()">成为会员</button> </div> </div> </div> <!-- 小票模态框 --> <div id="receiptModal" class="receipt-modal"> <div class="receipt-modal-content"> <span class="close-button" onclick="closeReceiptModal()">×</span> <h2>小票</h2> <p id="receipt-content"></p> </div> </div> <script> let dishes = [ { name: '宫保鸡丁', price: 28, status: true }, { name: '麻婆豆腐', price: 22, status: true }, { name: '鱼香肉丝', price: 25, status: true }, { name: '清蒸鲈鱼', price: 35, status: true } ]; let cart = []; let balance = 0; let isMember = false; let orderNumber = 1; function updateMenuDisplay() { const menuItemsDiv = document.getElementById('menu-items'); menuItemsDiv.innerHTML = ''; dishes.forEach((dish, index) => { const itemDiv = document.createElement('tr'); itemDiv.innerHTML = ` <td>${dish.name}</td> <td>¥${dish.price.toFixed(2)}</td> <td>${dish.status ? '上架' : '下架'}</td> <td> ${dish.status ? `<button οnclick="addToCart('${dish.name}', ${dish.price})">加入购物车</button>` : ''} <button οnclick="toggleStatus(${index})">${dish.status ? '下架' : '上架'}</button> </td> `; menuItemsDiv.appendChild(itemDiv); }); // 更新修改菜品信息的下拉框 const modifyDishSelect = document.getElementById('dish-to-modify'); modifyDishSelect.innerHTML = '<option value="">选择菜品</option>'; dishes.forEach(dish => { const option = document.createElement('option'); option.value = dish.name; option.textContent = dish.name; modifyDishSelect.appendChild(option); }); } function addToCart(name, price) { const existingItem = cart.find(item => item.name === name); if (existingItem) { existingItem.quantity++; } else { cart.push({ name, price, quantity: 1 }); } updateCartDisplay(); } function updateCartDisplay() { const cartItemsDiv = document.getElementById('cart-items'); cartItemsDiv.innerHTML = ''; let totalPrice = 0; let memberTotalPrice = 0; cart.forEach((item, index) => { const itemTotalPrice = item.price * item.quantity; const itemMemberPrice = itemTotalPrice * 0.8; // 会员价八折 const itemDiv = document.createElement('tr'); itemDiv.innerHTML = ` <td>${item.name}</td> <td>${item.quantity}</td> <td>¥${item.price.toFixed(2)}</td> <td>¥${itemTotalPrice.toFixed(2)}</td> <td>¥${itemMemberPrice.toFixed(2)}</td> <td> <button οnclick="increaseQuantity(${index})">+</button> <button οnclick="decreaseQuantity(${index})">-</button> <button οnclick="removeFromCart(${index})">移除</button> </td> `; cartItemsDiv.appendChild(itemDiv); totalPrice += itemTotalPrice; memberTotalPrice += itemMemberPrice; }); document.getElementById('total-price').textContent = `总价: ¥${totalPrice.toFixed(2)}`; document.getElementById('member-price').textContent = `会员价: ¥${memberTotalPrice.toFixed(2)}`; } function increaseQuantity(index) { cart[index].quantity++; updateCartDisplay(); } function decreaseQuantity(index) { if (cart[index].quantity > 1) { cart[index].quantity--; } else { removeFromCart(index); } updateCartDisplay(); } function removeFromCart(index) { cart.splice(index, 1); updateCartDisplay(); } function checkout() { if (cart.length === 0) { alert('购物车为空,请先添加菜品!'); return; } let totalPrice = cart.reduce((sum, item) => sum + item.price * item.quantity, 0); let memberTotalPrice = totalPrice * 0.8; // 会员价八折 if (isMember && balance >= memberTotalPrice) { balance -= memberTotalPrice; document.getElementById('balance').textContent = `余额: ¥${balance.toFixed(2)}`; alert(`结算成功!会员价: ¥${memberTotalPrice.toFixed(2)}\n当前余额: ¥${balance.toFixed(2)}`); } else if (!isMember) { const payment = parseFloat(prompt(`请输入支付金额(总价: ¥${totalPrice.toFixed(2)})`)); if (isNaN(payment) || payment < totalPrice) { alert('支付金额不足,请重新输入!'); return; } const change = payment - totalPrice; alert(`结算成功!总价: ¥${totalPrice.toFixed(2)}\n支付金额: ¥${payment.toFixed(2)}\n找零: ¥${change.toFixed(2)}`); } else { alert('余额不足,请充值后再试!'); return; } printReceipt(); cart = []; updateCartDisplay(); } function addDish() { const name = document.getElementById('new-dish-name').value.trim(); const price = parseFloat(document.getElementById('new-dish-price').value); if (!name || isNaN(price)) { alert('请输入完整且有效的信息!'); return; } dishes.push({ name, price, status: true }); updateMenuDisplay(); clearAdminForm(); } function toggleStatus(index) { dishes[index].status = !dishes[index].status; updateMenuDisplay(); } function toggleAdminForm() { const form = document.getElementById('modify-dish-form'); form.style.display = form.style.display === 'none' ? 'block' : 'none'; } function loadDishInfo() { const selectedName = document.getElementById('dish-to-modify').value; const dish = dishes.find(d => d.name === selectedName); if (dish) { document.getElementById('modified-dish-name').value = dish.name; document.getElementById('modified-dish-price').value = dish.price; } } function updateDish() { const selectedName = document.getElementById('dish-to-modify').value; const newName = document.getElementById('modified-dish-name').value.trim(); const newPrice = parseFloat(document.getElementById('modified-dish-price').value); if (!selectedName || !newName || isNaN(newPrice)) { alert('请输入完整且有效的信息!'); return; } const dishIndex = dishes.findIndex(d => d.name === selectedName); if (dishIndex !== -1) { dishes[dishIndex].name = newName; dishes[dishIndex].price = newPrice; updateMenuDisplay(); clearModifyForm(); } } function clearAdminForm() { document.getElementById('new-dish-name').value = ''; document.getElementById('new-dish-price').value = ''; } function clearModifyForm() { document.getElementById('dish-to-modify').value = ''; document.getElementById('modified-dish-name').value = ''; document.getElementById('modified-dish-price').value = ''; } function recharge() { const amount = parseFloat(document.getElementById('recharge-amount').value); if (isNaN(amount) || amount <= 0) { alert('请输入有效的充值金额!'); return; } balance += amount; document.getElementById('balance').textContent = `余额: ¥${balance.toFixed(2)}`; alert(`充值成功!充值金额: ¥${amount.toFixed(2)}\n当前余额: ¥${balance.toFixed(2)}`); document.getElementById('recharge-amount').value = ''; } function toggleMembership() { if (isMember) { alert('您已经是会员了!'); } else { isMember = true; document.getElementById('membership-status').textContent = '当前状态: 会员'; alert('恭喜您成为会员!现在您可以享受八折优惠。'); } } function printReceipt() { if (cart.length === 0) { alert('购物车为空,无法打印小票!'); return; } const receiptContent = document.getElementById('receipt-content'); receiptContent.innerHTML = ''; const currentTime = new Date().toLocaleString(); let receiptText = `点餐号: ${orderNumber}<br>`; receiptText += `点餐时间: ${currentTime}<br><br>`; receiptText += `<table style="width: 100%; border-collapse: collapse;">`; receiptText += `<thead><tr><th>菜品名称</th><th>数量</th><th>单价</th><th>总价</th></tr></thead><tbody>`; cart.forEach(item => { const itemTotalPrice = item.price * item.quantity; receiptText += `<tr><td>${item.name}</td><td>${item.quantity}</td><td>¥${item.price.toFixed(2)}</td><td>¥${itemTotalPrice.toFixed(2)}</td></tr>`; }); receiptText += '</tbody></table><br>'; const totalPrice = cart.reduce((sum, item) => sum + item.price * item.quantity, 0); const memberTotalPrice = totalPrice * 0.8; // 会员价八折 receiptText += `总价: ¥${totalPrice.toFixed(2)}<br>`; if (isMember) { receiptText += `会员价: ¥${memberTotalPrice.toFixed(2)}<br>`; } receiptContent.innerHTML = receiptText; openReceiptModal(); orderNumber++; // 增加订单号 } function openReceiptModal() { document.getElementById('receiptModal').style.display = 'block'; } function closeReceiptModal() { document.getElementById('receiptModal').style.display = 'none'; } // 初始化显示 updateMenuDisplay(); </script> </body> </html> 为什么加入购物车按钮无法触发事件
最新发布
11-19
from dataclasses import dataclass import time from datetime import datetime from pathlib import Path from typing import List from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.remote.webelement import WebElement from contextlib import contextmanager import tkinter as tk @dataclass class EmailInfo: text: str element: WebElement @dataclass class DownloadConfig: folder_name: str patterns: List[str] @dataclass class LoginConfig: """登录配置""" base_url: str = "http://10.190.188.246/nsmail/index.html#login" username: str = "gwjxd_zhzx" password: str = "ZHzx@1108" class RevealDownloader: def __init__(self): self.today = datetime.now() self.month = str(self.today.month).lstrip('0') self.day = str(self.today.day).lstrip('0') self.base_path = Path('E:/GYK运行揭示1.5编辑') self.date_folder = f'{self.month}月{self.day}日揭示上午版' self.login_config = LoginConfig() self.setup_download_configs() self.driver = self.setup_chrome_driver() def setup_download_configs(self) -> None: """设置下载配置""" self.download_configs = { 'liuji': DownloadConfig( folder_name=f'4-柳机({self.month}月{self.day}日上午版)', patterns=[f"{self.month}月{self.day}日上午运行揭示正式版", f"{self.month}月{self.day}日上午运行揭示正式版(无新令)"] ), 'changguibao': DownloadConfig( folder_name=f'5-长轨包({self.month}月{self.day}日上午版)', patterns=[f"{self.month}月{self.day}日上午全线长轨达示包", f"{self.month}月{self.day}日上午工机段全线长轨达示包"] ) } def setup_chrome_driver(self) -> webdriver.Chrome: """配置Chrome浏览器""" options = Options() options.binary_location = r"D:\软件安装\特殊\Chrome 懒人绿色版\Chrome\chrome.exe" options.add_argument("--disable-extensions") options.add_argument("--no-sandbox") options.add_argument("--disable-gpu") options.add_argument('--lang=zh-CN') options.add_argument("--disable-blink-features=AutomationControlled") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) prefs = { "profile.default_content_setting_values.automatic_downloads": 1, "download.prompt_for_download": False, "download.directory_upgrade": True, "safebrowsing.enabled": True } options.add_experimental_option("prefs", prefs) service = Service(r"D:\软件安装\特殊\Chrome 懒人绿色版\Chrome\chromedriver.exe") return webdriver.Chrome(service=service, options=options) def wait_for_element(self, by: By, value: str, timeout: int = 10) -> WebElement: """等待元素加载""" wait = WebDriverWait(self.driver, timeout) return wait.until(EC.presence_of_element_located((by, value))) def wait_for_clickable_element(self, by: By, value: str, timeout: int = 10) -> WebElement: """等待元素可点击""" wait = WebDriverWait(self.driver, timeout) return wait.until(EC.element_to_be_clickable((by, value))) def login(self) -> bool: """登录到邮箱系统""" try: print("\n开始登录邮箱系统...") # 访问登录页面 print(f"访问登录页面: {self.login_config.base_url}") self.driver.get(self.login_config.base_url) time.sleep(8) # 增加等待时间,让页面完全加载 print("页面加载完成,开始查找元素...") # 首先检查页面是否正确加载 print(f"当前页面标题: {self.driver.title}") print(f"当前页面URL: {self.driver.current_url}") # 搜索所有可能的输入框 print("\n搜索页面中的输入框...") all_inputs = self.driver.find_elements(By.TAG_NAME, "input") print(f"找到 {len(all_inputs)} 个输入框:") username_field = None password_field = None for i, input_elem in enumerate(all_inputs): try: input_id = input_elem.get_attribute("id") or "无ID" input_type = input_elem.get_attribute("type") or "无类型" input_placeholder = input_elem.get_attribute("placeholder") or "无placeholder" input_name = input_elem.get_attribute("name") or "无name" print(f" 输入框{i+1}: ID='{input_id}', type='{input_type}', placeholder='{input_placeholder}', name='{input_name}'") # 识别用户名输入框 if (input_id == "username" or "邮箱账号" in input_placeholder or "username" in input_name.lower() or "user" in input_id.lower()): username_field = input_elem print(f" -> 识别为用户名输入框") # 识别密码输入框 elif (input_id == "password" or input_type == "password" or "密码" in input_placeholder or "password" in input_name.lower()): password_field = input_elem print(f" -> 识别为密码输入框") except Exception as e: print(f" 检查输入框{i+1}时出错: {e}") # 输入用户名 if username_field: print(f"\n开始输入用户名: {self.login_config.username}") try: # 多种输入方式 self.driver.execute_script("arguments[0].focus();", username_field) username_field.clear() time.sleep(0.5) username_field.send_keys(self.login_config.username) time.sleep(0.5) # 验证输入结果 entered_value = username_field.get_attribute("value") print(f"用户名输入结果: '{entered_value}'") if entered_value != self.login_config.username: print("用户名输入不完整,尝试JS输入...") self.driver.execute_script(f"arguments[0].value = '{self.login_config.username}';", username_field) # 触发输入事件 self.driver.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));", username_field) except Exception as e: print(f"输入用户名时出错: {e}") else: print("❌ 未找到用户名输入框") return False # 输入密码 if password_field: print(f"\n开始输入密码...") try: self.driver.execute_script("arguments[0].focus();", password_field) password_field.clear() time.sleep(0.5) password_field.send_keys(self.login_config.password) time.sleep(0.5) # 验证密码是否输入(密码框通常不会显示实际值) entered_value = password_field.get_attribute("value") print(f"密码输入长度: {len(entered_value) if entered_value else 0}") if not entered_value or len(entered_value) == 0: print("密码输入失败,尝试JS输入...") self.driver.execute_script(f"arguments[0].value = '{self.login_config.password}';", password_field) self.driver.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));", password_field) except Exception as e: print(f"输入密码时出错: {e}") else: print("❌ 未找到密码输入框") return False # 查找登录按钮 print("\n搜索登录按钮...") login_button = None # 搜索所有可能的按钮元素 button_selectors = [ ("按钮标签", "//button"), ("输入按钮", "//input[@type='button' or @type='submit']"), ("包含登录的元素", "//*[contains(text(), '登录')]"), ("class包含btn的元素", "//*[contains(@class, 'btn')]"), ("class包含log的元素", "//*[contains(@class, 'log')]"), ("p标签", "//p") ] for desc, selector in button_selectors: try: elements = self.driver.find_elements(By.XPATH, selector) print(f" {desc}: 找到 {len(elements)} 个") for elem in elements: try: text = elem.text.strip() class_name = elem.get_attribute("class") or "" tag_name = elem.tag_name if text or "btn" in class_name.lower() or "log" in class_name.lower(): print(f" - {tag_name}: '{text}', class='{class_name}'") if ("登录" in text or "log" in class_name.lower()) and not login_button: login_button = elem print(f" -> 选择为登录按钮") except: pass except Exception as e: print(f" 搜索{desc}时出错: {e}") # 点击登录按钮 if login_button: print(f"\n点击登录按钮...") try: # 滚动到按钮位置 self.driver.execute_script("arguments[0].scrollIntoView(true);", login_button) time.sleep(1) # 尝试点击 self.driver.execute_script("arguments[0].click();", login_button) print("已点击登录按钮") time.sleep(8) except Exception as e: print(f"点击登录按钮时出错: {e}") return False else: print("❌ 未找到登录按钮") return False # 检查登录结果 print("\n检查登录结果...") current_url = self.driver.current_url print(f"登录后URL: {current_url}") if self.check_login_success(): print("✓ 登录成功!") return True else: print("❌ 登录失败") return False except Exception as e: print(f"登录过程出现异常: {str(e)}") import traceback traceback.print_exc() return False def check_login_success(self) -> bool: """检查登录是否成功""" try: # 增加等待时间 time.sleep(5) print("检查登录状态...") # 方法1: 检查URL是否发生变化 current_url = self.driver.current_url if "login" not in current_url.lower(): print("URL已改变,登录可能成功") return True # 方法2: 检查是否有错误提示 error_elements = self.driver.find_elements(By.XPATH, "//*[contains(text(), '错误') or contains(text(), '失败') or contains(text(), '用户名') or contains(text(), '密码')]") if error_elements: for error in error_elements: error_text = error.text.strip() if error_text and any(keyword in error_text for keyword in ['错误', '失败', '不正确', '无效']): print(f"发现错误信息: {error_text}") return False # 方法3: 检查是否不再有登录表单 login_forms = self.driver.find_elements(By.ID, "username") if not login_forms: print("登录表单已消失,登录成功") return True # 方法4: 检查是否有登录后的特征元素 # 邮件系统通常会有菜单、导航或者邮箱相关元素 success_indicators = [ "//span[contains(text(), '邮件')]", "//div[contains(@class, 'mail') or contains(@class, 'inbox')]", "//*[contains(text(), '收件箱') or contains(text(), '发件箱')]", "//a[contains(@href, 'mail') or contains(@href, 'inbox')]" ] for xpath in success_indicators: elements = self.driver.find_elements(By.XPATH, xpath) if elements: print(f"发现登录成功标志元素: {xpath}") return True # 方法5: 检查页面标题 page_title = self.driver.title if page_title and "登录" not in page_title and "login" not in page_title.lower(): print(f"页面标题已改变: {page_title}") return True print("未能确认登录状态") return False except Exception as e: print(f"检查登录状态时出错: {e}") return False def click_mail_menu(self) -> bool: """点击邮件菜单""" try: print("点击邮件菜单...") mail_span = self.wait_for_clickable_element( By.XPATH, "//span[contains(text(), '邮件')]" ) self.driver.execute_script("arguments[0].click();", mail_span) time.sleep(3) print("✓ 成功点击邮件菜单") return True except Exception as e: print(f"点击邮件菜单失败: {e}") return False def click_inbox(self) -> bool: """点击收件箱""" try: print("点击收件箱...") inbox_element = self.wait_for_clickable_element( By.XPATH, "//div[contains(@class, 'to_inbox') and contains(text(), '收邮件')]" ) self.driver.execute_script("arguments[0].click();", inbox_element) time.sleep(3) print("✓ 成功点击收件箱") return True except Exception as e: print(f"点击收件箱失败: {e}") return False def run_login_test(self) -> None: """运行登录测试""" try: print("开始登录测试...") print(f"目标网址: {self.login_config.base_url}") print(f"用户名: {self.login_config.username}") print(f"密码: {'*' * len(self.login_config.password)}") if self.login(): print("✓ 登录成功!") # 等待一下,让页面完全加载 time.sleep(3) # 打印当前页面信息用于调试 print(f"当前页面标题: {self.driver.title}") print(f"当前页面URL: {self.driver.current_url}") # 尝试寻找页面上的关键元素 print("\n搜索页面关键元素...") key_selectors = [ ("邮件相关", "//span[contains(text(), '邮件')]"), ("收件箱", "//*[contains(text(), '收件箱')]"), ("菜单项", "//div[@class]//span | //li//span | //a//span"), ("按钮", "//button | //input[@type='button'] | //div[@class*='btn']") ] for name, selector in key_selectors: try: elements = self.driver.find_elements(By.XPATH, selector) if elements: print(f" 找到{name}: {len(elements)}个") for i, elem in enumerate(elements[:3]): # 只显示前3个 try: text = elem.text.strip() if text: print(f" {i+1}. {text}") except: pass else: print(f" 未找到{name}") except Exception as e: print(f" 搜索{name}时出错: {e}") print("\n登录测试完成!") print("请查看浏览器窗口确认登录状态") print("按回车键继续...") input() else: print("✗ 登录失败") print("请检查:") print("1. 网址是否正确") print("2. 用户名和密码是否正确") print("3. 网络连接是否正常") except Exception as e: print(f"登录测试出错: {e}") import traceback traceback.print_exc() finally: print("5秒后关闭浏览器...") time.sleep(5) self.driver.quit() if __name__ == '__main__': try: RevealDownloader().run_login_test() except Exception as e: print(f"程序执行失败: {e}") time.sleep(3) 账号和密码输入没有问题,就是”登录”按钮,点击不了,实现不了登录
09-25
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值