概述
某些问卷还需要上传什么宣传图片才能提交,这样的话上一篇文章的代码就需要稍微改造一下了
准备工作
- selenium库
- ChromeDriver
- Xpath语法
Xpath语法大家可以在平台自行搜索资源学习,这里不展开说
分析问题
分析问卷
我们要实现自动填写问卷首先需要分析一下问卷星平台生成的问卷
测试问卷展示
问卷星平台要自动生成问卷应该是要有一定生成规则,基于此猜想我们进入开发者模式分析一下网页结构
问卷页面结构分析
如下图所示:
我们可以看到每个问题都被封装到了一个div盒子里,并且每个div的id规律太明显了,都是div加上这个问题的编号(1, 2, 3, … , n),所以我们可以直接写个for循环加上format就可以生成每个div的id了
编写代码
基于以上代码我们就可以编写代码了,基本思想如下:
- 先打开文件网页
1、判断是否是开放状态
是则计算开放还剩多少秒输出到控制台,时间到了后点击开始填写问卷
否则直接开始填写问卷 - 填写问卷
写一个for循环来枚举每个div的id,然后获取到问题的标题
如果是上传图片则直接上传文件,等待2秒后进入下一个循环
否则根据ID定位问题的输入框然后在定义的dict中拿出对应的数据填写 - 提交文件
代码
import time
from selenium import webdriver
import re
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.chrome.service import Service
def calc(time_str):
match = re.search(r"(\d+)天(\d+)时(\d+)分(\d+)秒", time_str)
# 如果匹配成功
if match:
days, hours, minutes, seconds = map(int, match.groups())
# 计算总秒数
total_seconds = days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60 + seconds
else:
# 如果匹配失败,可以设置一个默认值或抛出异常
total_seconds = None
return total_seconds
# TODO 这里记得及时更新对应版本的driver
# 初始化浏览器驱动,这里填入你的chromedriver.exe的存放的绝对路径(从磁盘开始写)
# 指定chromedriver的路径
# 谷歌浏览器driver r"D:\ChromeDriver\chromedriver-win64\chromedriver-win64\chromedriver.exe"
# edge浏览器driver r"D:\EdgeDriver\edgedriver_win64\msedgedriver.exe"
chrome_driver_path = r"D:\ChromeDriver127\chromedriver136-win64\chromedriver-win64\chromedriver.exe"
# 使用Service对象
service = Service(executable_path=chrome_driver_path)
# 创建options对象(如果需要设置额外的选项)
options = webdriver.ChromeOptions()
# 或者可以使用其他浏览器的驱动,这里创建浏览器对象
# 初始化driver
browser = webdriver.Chrome(service=service, options=options)
# 准备资源,把可能用到的数据以key: value的形式存入下方字典中
information_dict = {
"校区": "xx校区",
"学院": "xx学院",
"专业": "xxxx",
"班级": "xxxx",
"姓名": "spider",
"学号": "201700707",
"QQ": "123456789",
"年级": "2017",
"性别": "男",
"手机号": "1123456783",
"电话": "1123456783",
"file": r"E:\PythonExperiment\ObjectLearn\images\test.png"
}
def get_key(key_info: str):
for key_ in information_dict.keys():
if key_.lower() in key_info.lower():
return key_
# 打开网页
# TODO 这里填写你要填写的问卷url
url = "https://your url "
browser.get(url)
try:
while True:
try:
time_waite = calc(browser.find_element(By.XPATH, "//div[@id='divStartTimeTip']").text)
except NoSuchElementException:
time_waite = 0
except:
continue
if time_waite > 0:
print(f"还需等待: {time_waite}秒")
time.sleep(2)
if time_waite == 0 or time_waite is None:
break
browser.find_element(By.XPATH, "//div[@id='countdownHtml']//a").click()
time.sleep(2) # 等待页面打开 可以根据需要自己设置时间
except NoSuchElementException:
pass
# 填写表单
for index in range(1, 10):
searchID = f"q{index}"
try:
key_info = browser.find_element(By.XPATH, f"//div[@id='div{index}']//div[@class='topichtml']").text
# 根据Xpath语法获取到第index个问题
if "图片" in key_info.lower():
# 说明当前项是需要上传图片的
upload_button = browser.find_element(By.XPATH, f'//div[@id="div{index}"]//input') # 获取到输入框
upload_button.send_keys(information_dict.get("file")) # 上传图片
time.sleep(1) # 等待图片上传完
continue
text = browser.find_element(By.ID, searchID) # 根据ID定位到指定的输入框
key = get_key(key_info)
text.send_keys(information_dict.get(key, "x")) # 没有对应属性时,将填入x
except Exception as e:
print(f"Failed to fill in question {index}: {e}")
break
# 查找并点击按钮
try:
while True:
# 点击提交按钮
button = browser.find_element(By.ID, 'ctlNext') # 根据ID来定位提交按钮
if button is not None:
button.click() # 点击提交按钮
break
# 等待新的元素出现,这表明页面已经成功加载了下一个步骤
WebDriverWait(browser, 10).until(
ec.presence_of_element_located((By.ID, 'divdsc'))
)
print("Click was successful.")
except Exception as e:
print(f"Failed to click the button: {e}")
# 关闭浏览器
browser.quit()
效果展示
图片资源
我测试用的图片时仙剑三中的白豆腐
注意事项
在填写或者等待文件时最好不要将打开的chrome页面最小化或放置到其它界面之后
注意修改TODO部分的内容
如果有任何问题或改进意见欢迎在评论区讨论