0


基于selenium实现自动填写问卷星的问卷调查

你是否还在为学校天天发的问卷调查而苦恼?

你是否还在为天天填写朋友的问卷调查而苦恼?

你是否还在为没人帮你填写问卷调查而苦恼?

废话不多说,直接上解决方案:

没用用过selenium的小朋友记得先安装配置一下:谷歌浏览器驱动的安装及selenium的安装与使用 - 知乎

防止有人不看参数说明,再写一遍:

url         为问卷地址参数,

answers     为答案参数
    用列表存放答案,比如如果有3题,第一题多选,第二题单选,第三题多选
    [
        [1, 2], 
        [2], 
        [2, 3]
    ]
    意思就是第一题选A,B     第二题选B      第三题选B,C

select      为模式选择参数,默认为2
    1: 自主模式,根据自己填写的answer进行填写问卷
    2: 随机模式,通过random生成随机数进行填写问卷

flag        为bool类型参数,默认为False
    值为True: 无头模式,即不显示浏览器
    值为False:   正常模式 

注意:由于时间有限,目前我只做了单选和多选这两类选择题的自动填写,后续有时间的话会继续更新其他类型的题;

实现思路都大差不差,大家也可以参考代码自己更新


2023年11月29日 20:51第一次更新

多了如下几种题型:

** type=1**

** type=5**

type=6

type=9

2023年12月5日第二次更新

更新了答案参数用法,由列表改为字典,更加人性化,操作更加简单,可以自己选择题目填写答案。

'''
url         为问卷地址参数,
answers     为答案参数
    用字典存放答案,比如如果有3题,第一题多选,第二题填空,第三题单选
    {
        1: [2, 4],
        2: "无建议",
        3: 3, 
    }
    意思就是第一题选B,D     第二题填无建议      第三题选C

select      为模式选择参数,默认为2
    1: 自主模式,根据自己填写的answer进行填写问卷
    2: 随机模式,通过random生成随机数进行填写问卷

flag        为bool类型参数,默认为False
    值为True: 无头模式,即不显示浏览器
    值为False:   正常模式 
'''

当填写问卷提交过快时,会有反爬,这次更新解决了三种反爬:

  1. 对话框确认验证
  2. 智能检测按钮验证
  3. 滑块验证

可以根据输入指定填写次数

下面直接上代码:

import random
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ChromeOptions, ActionChains

'''
url         为问卷地址参数,
answers     为答案参数
    用字典存放答案,比如如果有3题,第一题多选,第二题填空,第三题单选
    {
        1: [2, 4],
        2: "无建议",
        3: 3, 
    }
    意思就是第一题选B,D     第二题填无建议      第三题选C

select      为模式选择参数,默认为2
    1: 自主模式,根据自己填写的answer进行填写问卷
    2: 随机模式,通过random生成随机数进行填写问卷

flag        为bool类型参数,默认为False
    值为True: 无头模式,即不显示浏览器
    值为False:   正常模式 
'''

class WenJuanXing:
    def __init__(self, url, answers, select=2, flag=False):
        # 初始化变量
        self.driver = None
        self.url = url
        self.answers = answers
        self.select = select
        # 初始化浏览器驱动
        self.options = ChromeOptions()
        self.options.headless = flag
        self.options.add_experimental_option('excludeSwitches', ['enable-automation'])
        self.options.add_experimental_option('useAutomationExtension', False)

    def parse(self):
        divs = self.driver.find_elements(By.CSS_SELECTOR, '.field.ui-field-contain')  # 拿到所有的问题
        for div in divs:
            div_num = divs.index(div) + 1  # 题号
            div_type = int(div.get_attribute('type'))  # 问题类型

            if div_type == 1:  # 填空题
                question = div.find_element(By.CSS_SELECTOR, 'input')
                if self.select == 1:
                    question.send_keys(self.answers[div_num])
                else:
                    input_type = question.get_attribute('type')
                    if input_type == "text":
                        question.send_keys("无建议")

                    elif input_type == "tel":
                        question.send_keys("18")

            if div_type == 3:  # 单选题
                checks = div.find_elements(By.CSS_SELECTOR, '.ui-radio')  # 拿到所有的选项
                if self.select == 1:  # 模式1:自主模式
                    checks[self.answers[div_num] - 1].click()
                else:  # 模式2:随机模式
                    check_num = len(checks)  # 选项数目
                    ans = random.randint(1, check_num)  # 随机生成答案
                    checks[ans - 1].click()

            if div_type == 4:  # 多选题
                checks = div.find_elements(By.CSS_SELECTOR, '.ui-checkbox')  # 拿到所有选项
                if self.select == 1:  # 模式1:自主模式
                    for ans in self.answers[div_num]:
                        checks[ans - 1].click()
                else:  # 模式2:随机模式
                    check_num = len(checks)  # 选项数目
                    num = random.randint(1, check_num)  # 随机生成选项数
                    ansArr = []  # 随机生成的答案数组
                    for i in range(num):
                        c = random.randint(1, check_num)  # 随机生成答案
                        if c not in ansArr:
                            ansArr.append(c)
                    for ans in ansArr:  # 根据随机数组里的答案进行选择
                        checks[ans - 1].click()

            if div_type == 5:
                lis = div.find_elements(By.CSS_SELECTOR, '.onscore>li')
                if self.select == 1:
                    lis[answers[div_num] - 1].click()
                else:
                    lis_num = len(lis)
                    ans = random.randint(1, lis_num)
                    lis[ans - 1].click()

            if div_type == 6:
                trs = div.find_elements(By.CSS_SELECTOR, 'tr[tp="d"]')
                for tr in trs:
                    tds = tr.find_elements(By.CSS_SELECTOR, 'td>a')
                    if self.select == 1:
                        tr_index = trs.index(tr)
                        tds[self.answers[div_num][tr_index] - 1].click()
                    else:
                        td_num = len(tds)
                        ans = random.randint(1, td_num)  # 随机生成答案
                        tds[ans - 1].click()

            if div_type == 9:
                questions = div.find_elements(By.CSS_SELECTOR, 'input')
                for question in questions:
                    if self.select == 1:
                        que_index = questions.index(question)
                        question.send_keys(self.answers[div_num][que_index])
                    else:
                        input_type = question.get_attribute('type')
                        inputmode = question.get_attribute('inputmode')
                        if input_type == "text":
                            if inputmode == "decimal":
                                min_num = int(question.get_attribute('min'))
                                max_num = int(question.get_attribute('max'))
                                ans = random.randint(min_num, max_num)
                                question.send_keys(ans)

            print(f'第{div_num}题已做完')
        self.driver.find_element(By.CSS_SELECTOR, '#ctlNext').click()  # 提交
        # 验证
        self.verify()
        print('提交成功')

    def verify(self):
        try:
            self.driver.find_element(By.CSS_SELECTOR, '#layui-layer1 .layui-layer-btn0').click()
            time.sleep(1)
            print('点击对话框确认验证')
        except:
            print('没有对话框验证')
        try:
            self.driver.find_element(By.CSS_SELECTOR, '#rectMask').click()
            time.sleep(3)
            print('有智能检测按钮验证')
        except:
            print('没有智能检测按钮验证')
            # 滑块验证
        try:
            slider = self.driver.find_element(By.XPATH, '//*[@id="nc_1__scale_text"]/span')
            if str(slider.text).startswith("请按住滑块"):
                width = slider.size.get('width')
                ActionChains(self.driver).drag_and_drop_by_offset(slider, width, 0).perform()
                print('滑块验证')
        except:
            print('没有滑块验证')

    def run(self):
        # 启动浏览器跳转到答题页面
        self.driver = webdriver.Chrome(options=self.options)
        self.driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": """
                            Object.defineProperty(navigator, 'webdriver', {
                              get: () => undefined
                            })
                          """
        })
        self.driver.get(self.url)
        self.driver.implicitly_wait(5)
        self.driver.maximize_window()  # 最大化浏览器窗口
        # 做题
        self.parse()
        # 阻塞和关闭
        # time.sleep(1)
        # input()
        self.driver.close()

if __name__ == '__main__':
    url = '问卷url'
    answers = {
        1: [2, 4],  # 1
        2: [2, 5],  # 2
        3: 3,  # 3·
        4: [1, 3, 5],  # 4
        5: [1, 2, 4],  # 5
        6: 2,  # 6·
        7: 3,  # 7·
        8: [4, 5],  # 8
        9: 1,  # 9·
        10: 2,  # 10·
        11: [2, 4, 5],  # 11
        12: [1, 3, 4],  # 12
        13: [1, 4, 5],  # 13
        14: [1, 2, 5],  # 14
        15: 1  # 15·
    }

    select = 2
    flag = False
    wenjuan = WenJuanXing(url, answers, select=select, flag=False)
    # wenjuan.run()
    num = int(input('请输入你要提交的次数'))
    for i in range(num):
        print(f'===============第{i+1}次==================')
        wenjuan.run()
标签: selenium python 爬虫

本文转载自: https://blog.csdn.net/qq_64997449/article/details/134695508
版权归原作者 Mount〆 所有, 如有侵权,请联系我们删除。

“基于selenium实现自动填写问卷星的问卷调查”的评论:

还没有评论