萌生想法的原因

学校的一些学分要自己抢公众号的活动修满的,要蹲点等公众号发的定时问卷开始填写,几乎秒没。

每次和舍友一起抢,发现大家手速网速各有不同,最后几家欢喜几家愁。

于是萌生了想法——通过代码解决这个问卷星抢活动,定时定点按照相关内容填写,然后自动提交。

目前只在学校学过一点简单的python,经过查阅了一番资料终于弄出了一个符合我目前设想的效果。

第一代代码

在微信公众号找到了一段代码,修改了一些参数打算就开始run了。

1.参考的代码

2.代码展示

import time
from selenium import webdriver
#启动谷歌浏览器
driver = webdriver.Chrome()
driver.maximize_window()
    
driver.implicitly_wait(2) 
    
driver.get("问卷网址")  # 输入网址
def dingshikQ(time, driver, name, nianji, number, Email):

    time_start = time.time() #开始计时
    print(time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime()))    
    driver.refresh() 
            
    #设置显式等待
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium import webdriver
    wait1 = webdriver.support.wait.WebDriverWait(driver,60,0.01)
    wait1.until(EC.presence_of_element_located((By.XPATH,"//div[contains(text(),'姓名')]/following-sibling::div[1]/input[1]")))
            
           
    # 开始填写    

    driver.find_element_by_xpath("//div[contains(text(),'姓名')]/following-sibling::div[1]/input[1]").send_keys("%s"%name) #输入姓名
            
    driver.find_element_by_xpath("//div[contains(text(),'年级')]/following-sibling::div[1]/input[1]").send_keys("%s"%nianji) #输入年级
            
    driver.find_element_by_xpath("//div[contains(text(),'学号')]/following-sibling::div[1]/input[1]").send_keys("%s"%number) #输入学号
            
    driver.find_element_by_xpath("//div[contains(text(),'邮箱')]/following-sibling::div[1]/input[1]").send_keys("%s"%Email) #输入邮箱
            
    # 点击提交
    driver.find_element_by_xpath("//div[contains(text(),'提交')]").click()
    
    if '请点击'in driver.find_element_by_xpath("//div[contains(text(),'请点击')]").text:
        driver.refresh() # #浏览器刷新(点击刷新按钮)
                
        wait2 = webdriver.support.wait.WebDriverWait(driver,60,0.01)
        wait2.until(EC.presence_of_element_located((By.XPATH,"//div[contains(text(),'是否继续')]")))
        driver.find_element_by_xpath("//button[contains(text(),'确认')]").click()
                
        wait3 = webdriver.support.wait.WebDriverWait(driver,60,0.01)
        wait3.until(EC.presence_of_element_located((By.XPATH,"//div[contains(text(),'提交')]"))) #这里必须是三个括号
        driver.find_element_by_xpath("//div[contains(text(),'提交')]").click()
                         
    time_end = time.time()    #结束计时
    time_c= time_end - time_start   #运行所花时间
    print('time cost=%.1fs'%time_c)
name='姓名'
nianji='年级'
number='12345678'
Email='12345678@163.com' 
dingshikQ(time, driver, name, nianji, number, Email)

3.发现的问题及解决方案

修改了一些参数run了以后,发现run不起来。经过一番资料查阅,发现是selenium库的更新换代,引用一些模块的时候方式变化了。

然后就增加了‘from selenium.webdriver.support.wait import WebDriverWait‘的引用和修改了每一条xpath的引用,代码终于run起来了

引入WebDriverWait模块参考的博客

xpath路径引用方式的修改参考博客

第二代代码

1.代码展示和效果图

import time
from selenium import webdriver
#启动火狐浏览器
driver = webdriver.Firefox()
driver.maximize_window()
    
driver.implicitly_wait(2) 
    
driver.get("问卷地址")  # 输入网址

def dingshikQ(time, driver, name, nianji, number, Email):

    time_start = time.time() #开始计时
    print(time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime()))#输出本地时间    
    driver.refresh() #刷新浏览器
            
    #设置显式等待
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    wait1 = webdriver.support.wait.WebDriverWait(driver,60,0.01)
    wait1.until(EC.presence_of_element_located((By.XPATH,"//div[contains(text(),'姓名')]/following-sibling::div[1]/input[1]")))
            
           
    # 开始填写    

    driver.find_element(By.XPATH,"//div[contains(text(),'姓名')]/following-sibling::div[1]/input[1]").send_keys("%s"%name) #输入
            
    driver.find_element(By.XPATH,"//div[contains(text(),'年级')]/following-sibling::div[1]/input[1]").send_keys("%s"%nianji) #输入
            
    driver.find_element(By.XPATH,"//div[contains(text(),'学号')]/following-sibling::div[1]/input[1]").send_keys("%s"%number) #输入
            
    driver.find_element(By.XPATH,"//div[contains(text(),'邮箱')]/following-sibling::div[1]/input[1]").send_keys("%s"%Email) #输入
            
    # 点击提交
    driver.find_element(By.XPATH,"//div[contains(text(),'提交')]").click()
    
    if '请点击'in driver.find_element(By.XPATH,"//div[contains(text(),'请点击')]").text:
        driver.refresh() # #浏览器刷新(点击刷新按钮)
                
        wait2 = webdriver.support.wait.WebDriverWait(driver,60,0.01)
        wait2.until(EC.presence_of_element_located((By.XPATH,"//div[contains(text(),'是否继续')]")))
        driver.find_element(By.XPATH,"//button[contains(text(),'确认')]").click()
                
        wait3 = webdriver.support.wait.WebDriverWait(driver,60,0.01)
        wait3.until(EC.presence_of_element_located((By.XPATH,"//div[contains(text(),'提交')]"))) #这里必须是三个括号
        driver.find_element(By.XPATH,"//div[contains(text(),'提交')]").click()
                         
    time_end = time.time()    #结束计时
    time_c= time_end - time_start   #运行所花时间
    print('time cost=%.1fs'%time_c)
name='姓名'
nianji='年级'
number='12345678'
Email='12345678@163.com' 
dingshikQ(time, driver, name, nianji, number, Email)




python 问卷系统 python自动填问卷星 详细代码_反爬虫


2.发现的问题

run了以后电脑自动打开并填写了,但会遇到一个智能验证的按钮,电脑操作太快没反应过就到了上述画面。即使我点了如图的确定再重新手打后,按智能验证的按钮还是不能通过。


python 问卷系统 python自动填问卷星 详细代码_python_02


3.解决方案:

上csdn搜索相关解决问卷星的智能验证按钮的问题。发现原来这是问卷星的发爬虫的一种机制,通过识别selenium就会弹出这个按钮。目前最新能够解决的办法是:

①下载旧版chrome浏览器

要用chrome浏览器打开问卷地址,而且是还要下载旧版的chrome浏览器复制旧版的chrome.exe到python的工作目录。

参考博客

下载旧版chrome并复制到python工作目录参考博客

②引入一段反反爬虫的代码

代码具体如下:
url = "问卷地址" #实例url

option = webdriver.ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(service=s,options=option)
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
driver.get(url)
参考博客

引入反反爬虫参考代码

③模拟点击智能验证按钮的代码:

代码具体如下
# 先点确认
        try:
            browser.find_element(By.XPATH, '//*[@id="layui-layer1"]/div[3]/a[1]').click()
            time.sleep(1)
        except:
            pass
        # 再点智能验证提示框,进行智能验证
        try:
            browser.find_element(By.XPATH, '//*[@id="SM_BTN_WRAPPER_1"]').click()
            time.sleep(3)
        except:
            pass
————————————————
版权声明:本文为CSDN博主「理工大猪猪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:
参考博客

点击智能验证按钮的代码参考博客

修改后的第三代代码

1.代码展示

按照上述操作修改了自己的代码如下:

import time
from selenium import webdriver
#反反爬虫
from selenium.webdriver.chrome.options import Options
url = "问卷地址" #实例url

option = webdriver.ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=option)
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
driver.get(url)


#定义抢课函数
def dingshikQ(time, driver, name, nianji, number, Email):

    time_start = time.time() #开始计时
    print(time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime()))#输出本地时间    
    driver.refresh() #刷新浏览器
            
    #设置显式等待
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    wait1 = webdriver.support.wait.WebDriverWait(driver,60,0.01)
    wait1.until(EC.presence_of_element_located((By.XPATH,"//div[contains(text(),'姓名')]/following-sibling::div[1]/input[1]")))
            
           
    # 开始填写    

    driver.find_element(By.XPATH,"//div[contains(text(),'姓名')]/following-sibling::div[1]/input[1]").send_keys("%s"%name) #输入
            
    driver.find_element(By.XPATH,"//div[contains(text(),'学号')]/following-sibling::div[1]/input[1]").send_keys("%s"%nianji) #输入
            
    driver.find_element(By.XPATH,"//div[contains(text(),'学院')]/following-sibling::div[1]/input[1]").send_keys("%s"%number) #输入
            
    driver.find_element(By.XPATH,"//div[contains(text(),'请输入您的手机号码')]/following-sibling::div[1]/input[1]").send_keys("%s"%Email) #输入

    
 # 点击提交
    driver.find_element(By.XPATH,"//div[contains(text(),'提交')]").click()
# 先点确认
    try:
        driver.find_element(By.XPATH, '//*[@id="layui-layer1"]/div[3]/a[1]').click()
        time.sleep(1)
    except:
        pass
        # 再点智能验证提示框,进行智能验证
    try:
        driver.find_element(By.XPATH, '//*[@id="SM_BTN_WRAPPER_1"]').click()
        time.sleep(3)
    except:
        pass

    time_end = time.time()    #结束计时
    time_c= time_end - time_start   #运行所花时间
    print('time cost=%.1fs'%time_c)

name='林芝'
nianji='大一'
number='12345678'
Email=159123456789
dingshikQ(time, driver, name, nianji, number, Email)

2.效果图


python 问卷系统 python自动填问卷星 详细代码_Email_03


3.发现的问题以及解决方案:

还是没能自动点击这个按钮。后来仔细对比自己的代码和原文博客的代码,原来是那段反反爬虫的代码要放在定义的函数下面。

对比参考的博客

然后就run了,在问卷星发布的问卷后台那里一看,果然看到了自己刚交的问卷。

第四代代码(终版)

代码展示

还添加了定时的效果(还有一些小改动,删除了函数的形参driver、显示等待、计时功能,添加了print('恭喜!问卷提交成功!'))

#引入一些需要用到的库
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait


#定义抢活动函数
def dingshikQ(time, name, nianji, number, Email):

    
    while True:
        
        time_now=time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime())
    
        #定时问卷
        if time_now=="2023-02-08-19:28:00":
            #解决反爬虫的参数
            url = "https://www.wjx.cn/vm/P3JxRus.aspx" #实例url

            option = webdriver.ChromeOptions()
            option.add_experimental_option('excludeSwitches', ['enable-automation'])
            option.add_experimental_option('useAutomationExtension', False)
            driver = webdriver.Chrome(options=option)
            driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
            driver.get(url)
                
           
    # 开始填写

            driver.find_element(By.XPATH,"//div[contains(text(),'学院名称')]/following-sibling::div[1]/input[1]").send_keys("%s"%name) #输入
            
            driver.find_element(By.XPATH,"//div[contains(text(),'学号')]/following-sibling::div[1]/input[1]").send_keys("%s"%nianji) #输入
            
            driver.find_element(By.XPATH,"//div[contains(text(),'姓名')]/following-sibling::div[1]/input[1]").send_keys("%s"%number) #输入
            
            driver.find_element(By.XPATH,"//div[contains(text(),'专业')]/following-sibling::div[1]/input[1]").send_keys("%s"%Email) #输入

            submit = driver.find_element(By.XPATH,"//*[@id='ctlNext']")    #网页源代码的xpath
            submit.click()      #点击
    
    #延时 太快会被检测是脚本
            time.sleep(0.5)

    # 模拟点击智能验证按钮
    # 先点确认
            wait3 = webdriver.support.wait.WebDriverWait(driver,60,0.01)
            wait3.until(EC.presence_of_element_located((By.XPATH,'//*[@id="layui-layer1"]/div[3]/a[1]')))
            driver.find_element(By.XPATH,'//*[@id="layui-layer1"]/div[3]/a[1]').click()
            time.sleep(1)
    # 再点智能验证提示框,进行智能验证
            wait3 = webdriver.support.wait.WebDriverWait(driver,60,0.01)
            wait3.until(EC.presence_of_element_located((By.XPATH,'//*[@id="SM_BTN_WRAPPER_1"]')))
            driver.find_element(By.XPATH,'//*[@id="SM_BTN_WRAPPER_1"]').click()


            time.sleep(3)
    
            print('恭喜!问卷提交成功!')


name='经济与管理'
nianji='20975356'
number='小欧欧'
Email='工商管理'
dingshikQ(time, name, nianji, number, Email)

觉得还可以改善的地方:

①运行的时间问题

因为防止被检测出是脚本添加了sleep(),增加了运行时间;但是增加了运行时间同时降低提交问卷的速度,不利于和学校那些’手速怪‘竞争名额。(试过不用sleep,但是太短的时间后台收不到问卷)

②其他可能出现的情形

问卷还有微信登录和文本检测的功能,如何解决微信登录还有手机号码的输入时而文本时而数字的问题。

③做成一个插件

做成一个插件,一打开就有一个窗口填写相关的数值,不需要一直翻找代码那么麻烦