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

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

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

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

没用用过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: 正常模式

'''

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

对话框确认验证 智能检测按钮验证 滑块验证

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

 下面直接上代码:

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()

好文阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: