你是否還在為學(xué)校天天發(fā)的問卷調(diào)查而苦惱?
你是否還在為天天填寫朋友的問卷調(diào)查而苦惱?
你是否還在為沒人幫你填寫問卷調(diào)查而苦惱?
廢話不多說,直接上解決方案:
沒用用過selenium的小朋友記得先安裝配置一下:谷歌瀏覽器驅(qū)動的安裝及selenium的安裝與使用 - 知乎
?防止有人不看參數(shù)說明,再寫一遍:
url 為問卷地址參數(shù),answers 為答案參數(shù) 用列表存放答案,比如如果有3題,第一題多選,第二題單選,第三題多選 [ [1, 2], [2], [2, 3] ] 意思就是第一題選A,B 第二題選B 第三題選B,Cselect 為模式選擇參數(shù),默認為2 1: 自主模式,根據(jù)自己填寫的answer進行填寫問卷 2: 隨機模式,通過random生成隨機數(shù)進行填寫問卷 flag 為bool類型參數(shù),默認為False 值為True: 無頭模式,即不顯示瀏覽器 值為False: 正常模式
注意:由于時間有限,目前我只做了單選和多選這兩類選擇題的自動填寫,后續(xù)有時間的話會繼續(xù)更新其他類型的題;
實現(xiàn)思路都大差不差,大家也可以參考代碼自己更新
2023年11月29日 20:51第一次更新
多了如下幾種題型:
?type=1
?type=5
?
type=6
type=9
2023年12月5日第二次更新?
更新了答案參數(shù)用法,由列表改為字典,更加人性化,操作更加簡單,可以自己選擇題目填寫答案。
''' url 為問卷地址參數(shù), answers 為答案參數(shù) 用字典存放答案,比如如果有3題,第一題多選,第二題填空,第三題單選 { 1: [2, 4], 2: "無建議", 3: 3, } 意思就是第一題選B,D 第二題填無建議 第三題選C select 為模式選擇參數(shù),默認為2 1: 自主模式,根據(jù)自己填寫的answer進行填寫問卷 2: 隨機模式,通過random生成隨機數(shù)進行填寫問卷 flag 為bool類型參數(shù),默認為False 值為True: 無頭模式,即不顯示瀏覽器 值為False: 正常模式 '''當(dāng)填寫問卷提交過快時,會有反爬,這次更新解決了三種反爬:
對話框確認驗證 智能檢測按鈕驗證 滑塊驗證可以根據(jù)輸入指定填寫次數(shù)文章來源:http://www.zghlxwxcb.cn/news/detail-760853.html
?下面直接上代碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-760853.html
import random
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ChromeOptions, ActionChains
'''
url 為問卷地址參數(shù),
answers 為答案參數(shù)
用字典存放答案,比如如果有3題,第一題多選,第二題填空,第三題單選
{
1: [2, 4],
2: "無建議",
3: 3,
}
意思就是第一題選B,D 第二題填無建議 第三題選C
select 為模式選擇參數(shù),默認為2
1: 自主模式,根據(jù)自己填寫的answer進行填寫問卷
2: 隨機模式,通過random生成隨機數(shù)進行填寫問卷
flag 為bool類型參數(shù),默認為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
# 初始化瀏覽器驅(qū)動
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) # 選項數(shù)目
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) # 選項數(shù)目
num = random.randint(1, check_num) # 隨機生成選項數(shù)
ansArr = [] # 隨機生成的答案數(shù)組
for i in range(num):
c = random.randint(1, check_num) # 隨機生成答案
if c not in ansArr:
ansArr.append(c)
for ans in ansArr: # 根據(jù)隨機數(shù)組里的答案進行選擇
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):
# 啟動瀏覽器跳轉(zhuǎn)到答題頁面
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()
# 阻塞和關(guān)閉
# 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('請輸入你要提交的次數(shù)'))
for i in range(num):
print(f'===============第{i+1}次==================')
wenjuan.run()
到了這里,關(guān)于基于selenium實現(xiàn)自動填寫問卷星的問卷調(diào)查的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!