《使用Python实现问卷星调查问卷自动填写》

文章目录

  • 前言
  • 一、配置环境
  • 1.1 下载依赖selenium
  • 1.2 安装chrome驱动
  • 1.3 引入库
  • 二、简易版快速上手教程
  • 1.自定义变量
  • 2.自定以函数
  • 3 主函数编写
  • 三 逐步解析
  • 1 基础代码
  • 2 实现步骤
  • 四 代码
  • 总结

  • 前言

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

    物联沃分享整理
    物联沃-IOTWORD物联网 » 《使用Python实现问卷星调查问卷自动填写》

    发表评论