草庐IT

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

Yibaomeimei 2023-04-09 原文

文章目录


前言

如何使用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即找到了我们的问卷区域。

在该层下罗列了所以题目的信息元素。

顺着层级关系我们就能够找到对应的选项的位置在哪。

右键选中该部分,复制XPath则获取到了对应模块的按钮地址,比如该模块为
//*[@id=“div1”]/div[2]/div[1]/div
而我们就可以通过以下方法来使用他:

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
本文基于问卷演示了如何进行爬虫,对网页内容进行解析,只用作技术学习交流,勿用在其他不当用途上、一起提升网页操作相关的能力。

有关Python实现问卷星调查问卷自动填写的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  5. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  6. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  7. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  8. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  9. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  10. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

随机推荐