Python实现问卷星调查问卷自动填写

前言

如何使用python实现对问卷的自动填写提交任务并且还能解决智能验证问题。

一、配置环境

1.1 下载依赖selenium

selenium是一款网页爬虫重要的工具。

1.2 安装chrome驱动

这里需要准备chrome浏览器以及对应的驱动。需要注意的是驱动的版本需要和chrome保持一致。
chrome浏览器版自行查看本机安装版本。
在这里插入图片描述

chrome驱动下载链接 chrome驱动链接找到对应版本的驱动。
在这里插入图片描述
下载后将安装包解压(解压后为.exe文件)在自定义任意文件夹即可。

1.3 引入库

from selenium import webdriver
import numpy as np
import time
from selenium.webdriver.common.by import By

二、简易版快速上手教程

这部分的目的主要是快速上手应用到自己的问卷当中,如果该部分出现问题,那么可能是问卷星版本不同,默认的XPATH不同导致的,所以可以跳至 三 从原理进行根据自身情况量身打造。

1.自定义变量

代码如下(示例):
url = 'https://www.wjx.cn/vm/tMNr1Ba.aspx' # 问卷链接
path = r"E:\\chorme_qd\\chromedriver_win32\\chromedriver.exe" #前面下载的chrome驱动链接

2.自定以函数

定义选择方式。这里选择对多选题和单选题的选择方式为随机选取。

def selection(a): #随机选择 输入参数为任意个数str(xpath) 返回值为某一随机str(xpath)
    n = len(a)
    num = np.random.randint(1,n)
    for i in range(1,n+1,1):
        if(i==num):
            return a[num-1]
            
def delay_roll(driver, t=0.5, distance=200): #延时+屏幕滚动
    global roll_distance
    roll_distance = roll_distance + distance
    js="var q=document.documentElement.scrollTop=" + str(roll_distance)    #下拉像素(800是基于最顶端测算的距离)
    driver.execute_script(js)
    time.sleep(t)
    
def duoxuan(driver, num, nums): #多选题 num:题号  nums:选项个数
    xx = []
    for i in range(1, nums+1):
        xpath = '//*[@id="div' + str(num) +  '"]/div[2]/div[' + str(i) + "]/span/a"
        xx.append(xpath)
    n = len(xx)
    num = np.random.randint(2, n)
    ids = set(np.random.randint(0,n-1,num))
    for i in ids:
        time.sleep(1)
        driver.find_element(By.XPATH, xx[i]).click()
    delay_roll(driver, 0.5, 200) #延时0.5s,滚动200长度
    
def danxuan(driver, num, nums): #单选题 num:题号 nums:选项数量  driver:网页读取类
    xx = []
    for i in range(1, nums+1):
        xpath = '//*[@id="div' + str(num) +  '"]/div[2]/div[' + str(i) + "]/span/a"
        xx.append(xpath)
    driver.find_element(By.XPATH, selection(xx)).click()
    delay_roll(driver, 0.5, 200) #延时0.5s,滚动200长度

def tiankong(driver, num, text): #填空 num: 题号 text:内容
    driver.find_element(By.XPATH, '//*[@id="q' + num + '"]').send_keys(str(text))
    delay_roll(driver)
这里如果使用的当前版本最新的问卷,为了简易快速上手,全部采用默认值封装成函数。
下面编写主函数就非常简单易懂易上手。

3 主函数编写

def autoWrite(num):
    for i in range(num):
        print("正在执行操作......")
        # 给出所需的url和option参数
        url_survey = (url)  # 根据需要填写url
        #防止被浏览器识别为脚本
        option = webdriver.ChromeOptions()
        option.add_experimental_option('excludeSwitches', ['enable-automation'])
        option.add_experimental_option('useAutomationExtension', False)
        driver = webdriver.Chrome(executable_path=path, options=option)
        driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument',
                            {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'})
        driver.get(url_survey)
        time.sleep(0.2)
        
        #第一题 单选
        danxuan(driver, 1, 4)  #题号为1,有4个选项
        #第二题 填空 
        tiankong(driver, 2, "test") #题号为2,填写内容为:”test“
        #第三题 多选题
        duoxuan(driver, 3, 7) #题号为3,7个选项
        #第四题 样例的问卷中该单选题这个单选题选是的话还要继续填内容,没做这个,所以为了跑通测试选择否就行了。
        driver.find_element(By.XPATH, '//*[@id="div4"]/div[2]/div[2]/span/a').click()
        time.sleep(1)
        
        #点击提交
        driver.find_element(By.XPATH, '//*[@id="ctlNext"]').click()
        print('第'+str(i)+'次填写成功')
        time.sleep(1)
        # 模拟点击智能验证按钮
        # 先点确认
        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
        print("end")
        driver.quit()
        time.sleep(2)

在这部分,实际需要修改的呢就是以下这部分了:

		#第一题 单选
        danxuan(driver, 1, 4)  #题号为1,有4个选项
        #第二题 填空 
        tiankong(driver, 2, "test") #题号为2,填写内容为:”test“
        #第三题 多选题
        duoxuan(driver, 3, 7) #题号为3,7个选项

在默认你使用的问卷版本跟作者一样的话就可以只需要修改autoWrite中的以上部分的代码即可。
逻辑很简单,按照问卷排版格式,一条一条编写下来即可。比如上述三条代码的对应关系如下:
在这里插入图片描述

三 逐步解析

该部分将从原理出发来讲解如何编写全部代码。

1 基础代码

该部分作用还是选择题的选择策略自定义。

def selection(*a): #单选题 输入参数为任意个数str(xpath) 返回值为某一随机str(xpath)
    global flag
    n = len(a)
    num = np.random.randint(1,n)
    for i in range(1,n+1,1):
        if(i==num):
            flag = num
            return a[num-1]
def duoxuan(driver, a): #随机数生成
    n = len(a)
    num = np.random.randint(2, n)
    ids = set(np.random.randint(0,n-1,num))
    for i in ids:
        time.sleep(1)
        driver.find_element(By.XPATH, a[i]).click()
def delay_roll(driver, t, distance): #延时+滑动
    global roll_distance
    roll_distance = roll_distance + distance
    js="var q=document.documentElement.scrollTop=" + str(roll_distance)    #下拉像素(800是基于最顶端测算的距离)
    driver.execute_script(js)
    time.sleep(t)

2 实现步骤

对于选择的原理就是找到题中各个选项的XPATH地址即可。
首先、在问卷网页中按F12进入检查界面。
在这里插入图片描述
元素中通过一层一层的查找到id=divQuestion即找到了我们的问卷区域。
在这里插入图片描述
在该层下罗列了所以题目的信息元素。
在这里插入图片描述

driver.find_element(By.XPATH, '//*[@id="div1"]/div[2]/div[1]/div').click()

以上表示click点击该部分的意思。

基于 以上内容 基本上所有的模块都是可以通过这个方法找到他的XPath进行调用。
对于填空使用如下方法:

driver.find_element(By.XPATH, '//*[@id="q2"]').send_keys('text')

不同模块的XPath格式不同。

四 代码

最后附上二 三 部分的代码
二:

from selenium import webdriver
import numpy as np
import time
from selenium.webdriver.common.by import By


# option = webdriver.ChromeOptions()
# option.add_argument('headless')
url = 'https://www.wjx.cn/vm/tMNr1Ba.aspx'
path = r"E:\\chorme_qd\\chromedriver_win32\\chromedriver.exe"
roll_distance = 0
def selection(a): #单选题 输入参数为任意个数str(xpath) 返回值为某一随机str(xpath)
    n = len(a)
    num = np.random.randint(1,n)
    for i in range(1,n+1,1):
        if(i==num):
            return a[num-1]
def delay_roll(driver, t=0.5, distance=200): #延时+屏幕滚动
    global roll_distance
    roll_distance = roll_distance + distance
    js="var q=document.documentElement.scrollTop=" + str(roll_distance)    #下拉像素(800是基于最顶端测算的距离)
    driver.execute_script(js)
    time.sleep(t)
def duoxuan(driver, num, nums): #多选题 num:题号  nums:选项个数
    xx = []
    for i in range(1, nums+1):
        xpath = '//*[@id="div' + str(num) +  '"]/div[2]/div[' + str(i) + "]/span/a"
        xx.append(xpath)
    n = len(xx)
    num = np.random.randint(2, n)
    ids = set(np.random.randint(0,n-1,num))
    for i in ids:
        time.sleep(1)
        driver.find_element(By.XPATH, xx[i]).click()
def danxuan(driver, num, nums): #传入 num:题号 nums:选项数量  driver:网页读取类
    xx = []
    for i in range(1, nums+1):
        xpath = '//*[@id="div' + str(num) +  '"]/div[2]/div[' + str(i) + "]/span/a"
        xx.append(xpath)
    driver.find_element(By.XPATH, selection(xx)).click()
    delay_roll(driver, 0.5, 200) #延时0.5s,滚动200长度
def tiankong(driver, num, text): #num: 题号 text:内容
    driver.find_element(By.XPATH, '//*[@id="q' + str(num) + '"]').send_keys(str(text))
    delay_roll(driver)
def autoWrite(num):
    global roll_distance
    for i in range(num):
        roll_distance = 0
        print("正在执行操作......")
        # 给出所需的url和option参数
        url_survey = (url)  # 根据需要填写url
        #防止被浏览器识别为脚本
        option = webdriver.ChromeOptions()
        option.add_experimental_option('excludeSwitches', ['enable-automation'])
        option.add_experimental_option('useAutomationExtension', False)
        driver = webdriver.Chrome(executable_path=path, options=option)
        driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument',
                            {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'})
        driver.get(url_survey)
        time.sleep(0.2)

        #第一题 单选
        danxuan(driver, 1, 4)  #题号为1,有4个选项
        #第二题 填空 
        tiankong(driver, 2, "test") #题号为2,填写内容为:”test“
        #第三题 多选题
        duoxuan(driver, 3, 7) #题号为3,7个选项

        #第四题 样例的问卷中该单选题这个单选题选是的话还要继续填内容,没做这个,所以为了跑通测试选择否就行了。
        driver.find_element(By.XPATH, '//*[@id="div4"]/div[2]/div[2]/span/a').click()
        time.sleep(1)
        
        #点击提交
        driver.find_element(By.XPATH, '//*[@id="ctlNext"]').click()
        print('第'+str(i)+'次填写成功')
        time.sleep(1)
        # 模拟点击智能验证按钮
        # 先点确认
        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
        print("end")
        driver.quit()
        time.sleep(2)
autoWrite(3)

三:

from selenium import webdriver
import numpy as np
import time
from selenium.webdriver.common.by import By


# option = webdriver.ChromeOptions()
# option.add_argument('headless')
url = 'https://www.wjx.cn/vm/tMNr1Ba.aspx'
path = r"E:\\chorme_qd\\chromedriver_win32\\chromedriver.exe"
roll_distance = 0
def selection(a): #单选题 输入参数为任意个数str(xpath) 返回值为某一随机str(xpath)
    n = len(a)
    num = np.random.randint(1,n)
    for i in range(1,n+1,1):
        if(i==num):
            return a[num-1]
def delay_roll(driver, t=0.5, distance=200): #延时+屏幕滚动
    global roll_distance
    roll_distance = roll_distance + distance
    js="var q=document.documentElement.scrollTop=" + str(roll_distance)    #下拉像素(800是基于最顶端测算的距离)
    driver.execute_script(js)
    time.sleep(t)
def duoxuan(driver, xx): #多选题 num:题号  nums:选项个数
    n = len(xx)
    num = np.random.randint(2, n)
    ids = set(np.random.randint(0,n-1,num))
    for i in ids:
        time.sleep(1)
        driver.find_element(By.XPATH, xx[i]).click()
def autoWrite(num):
    global roll_distance
    for i in range(num):
        roll_distance = 0
        print("正在执行操作......")
        # 给出所需的url和option参数
        url_survey = (url)  # 根据需要填写url
        #防止被浏览器识别为脚本
        option = webdriver.ChromeOptions()
        option.add_experimental_option('excludeSwitches', ['enable-automation'])
        option.add_experimental_option('useAutomationExtension', False)
        driver = webdriver.Chrome(executable_path=path, options=option)
        driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument',
                            {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'})
        driver.get(url_survey)
        time.sleep(0.2)
        #第一题
        driver.find_element(By.XPATH, selection('//*[@id="div1"]/div[2]/div[1]/span/a',
                                                '//*[@id="div1"]/div[2]/div[2]/span/a',
                                                '//*[@id="div1"]/div[2]/div[3]/span/a',
                                                '//*[@id="div1"]/div[2]/div[4]/span/a')).click()
        # driver.find_element(By.XPATH, '//*[@id="q2"]').send_keys('money')
        js="var q=document.documentElement.scrollTop=400"  
        driver.execute_script(js)   
        #第二题//*[@id="q2"]
        time.sleep(1)
        driver.find_element(By.XPATH, '//*[@id="q2"]').send_keys('money')
        js="var q=document.documentElement.scrollTop=200"    #下拉像素(800是基于最顶端测算的距离)
        driver.execute_script(js)        #执行下拉像素操作
        #第三题
        time.sleep(1)
        duoxuan(driver, ('//*[@id="div3"]/div[2]/div[1]/span/a',
                                                '//*[@id="div3"]/div[2]/div[2]/span/a',
                                                '//*[@id="div3"]/div[2]/div[3]/span/a',
                                                '//*[@id="div3"]/div[2]/div[4]/span/a',
                                                '//*[@id="div3"]/div[2]/div[5]/span/a',
                                                '//*[@id="div3"]/div[2]/div[6]/span/a',
                                                '//*[@id="div3"]/div[2]/div[7]/span/a'))
        #第四题
        js="var q=document.documentElement.scrollTop=400"    #下拉像素(800是基于最顶端测算的距离)
        driver.execute_script(js)        #执行下拉像素操作
        time.sleep(1)
        driver.find_element(By.XPATH, '//*[@id="div4"]/div[2]/div[2]/span/a').click()
        time.sleep(1)
        driver.find_element(By.XPATH, '//*[@id="ctlNext"]').click()
        print('第'+str(i)+'次填写成功')
        time.sleep(2)
        
        # 模拟点击智能验证按钮
        # 先点确认//*[@id="layui-layer1"]/div[3]/a[1] //*[@id="SM_BTN_WRAPPER_1"]
        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
        # 再点智能验证提示框,进行智能验证
        # driver.find_element(By.XPATH,"//div[@id='captcha']").click()
        print("end")
        driver.quit()
        time.sleep(2)
autoWrite(3)

总结

参考博客:https://blog.csdn.net/DexiangPeng/article/details/121451375
本文基于问卷演示了如何进行爬虫,对网页内容进行解析,只用作技术学习交流,勿用在其他不当用途上、一起提升网页操作相关的能力。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年3月7日 上午11:13
下一篇 2023年3月7日 上午11:18

相关推荐