0%

Python selenium自动化刷问卷+绕过智能验证

  学校思政实践要收集1500份问卷,待在家里无聊就简单写了个用selenium模块实现的自动填写问卷星问卷的小程序。
  基本思路很简单
  1.先打开问卷的网址,按F12进开发者模式分析页面HTML,找到题目的选项按钮对应的HTML代码(例如:Q1的四个选项按钮都在a标签内,且rel属性值分别为q1_1,q1_2,q1_3,q1_4);
  2.在py中用slenium的find_element_by_xpath+click()方法实现模拟点击按钮,例如:

1
2
3
4
5
6
7
q1 = random()
if 0 <= q1 <= 0.5:
# 通过属性定位元素
# q1_1是Q1的第1个按钮
driver.find_element_by_xpath("//a[@rel='q1_1']").click()
else:
driver.find_element_by_xpath("//a[@rel='q1_2']").click()

  3.若想模拟人的选择偏好,就用随机数区间+if语句控制,无非就是多写几条语句;
  4.最后填写完问卷提交也是一样的,find_element找到提交按钮的html对应代码再click()。此时要注意——在py中用selenium模拟填写的问卷最后点击提交必定触发智能验证框:
在这里插入图片描述
  这时你无论用人手点击或者是再模拟点击都是没法验证成功的
在这里插入图片描述

  这是因为问卷xing网页有反爬机制会检查你是不是通过selenium访问网页的。大多数情况下,检测基本原理是检测当前浏览器窗口下的window.navigator对象是否包含webdriver这个属性。因为在正常使用浏览器的情况下,这个属性是undefined,然而一旦我们使用了selenium,selenium会给window.navigator设置webdriver属性。很多网站就通过JS判断如果webdrive 属性存在,那就直接屏蔽。

  网上搜了一下,基本看着都是用pyppeteer解决反爬的方法,安装python第三方库asyncio、pyppeteer和pyppeteer_stealth然后一顿操作猛如虎似乎可以绕过智能验证?这个方法我没试,大家可以试试看,附上相关博文:使用Python自动填写问卷星(pyppeteer反爬虫版)
  我参考了某位知乎答主的方法——
  通过 CDP 实现在每个页面刚加载的时候执行JS代码,执行的CDP方法叫作Page.addScriptToEvaluateOnNewDocument。传入一段JS代码:

1
2
3
4
5
6
7
8
url = "http://www.baidu.com" #实例url
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
browser = webdriver.Chrome(options=option)
browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
browser.get(url)

这样就可以在每次页面加载之前将webdriver属性置空从而躲过智能检测。

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
from selenium import webdriver
import time
from random import *

print("正在执行操作......")
# 给出所需的url和option参数
url_survey = ("https://www.wjx.cn/xx/xxxxxxx.aspx") # 根据需要填写url
option = webdriver.ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=option)
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'})
driver.get(url_survey)
time.sleep(2)

# 处理Q1
# 生成随机数,决定点哪个按钮
q1 = random()
if 0 <= q1 <= 0.5:
# 通过属性定位元素
# q1_1是Q1的第1个按钮
driver.find_element_by_xpath("//a[@rel='q1_1']").click()
else:
driver.find_element_by_xpath("//a[@rel='q1_2']").click()

# 处理Q2
# 生成随机数,决定点哪个按钮
q2 = random()
if 0 <= q2 <= 0.25:
driver.find_element_by_xpath("//a[@rel='q2_1']").click()
elif 0.25 < q2 <= 0.50:
driver.find_element_by_xpath("//a[@rel='q2_2']").click()
elif 0.50 < q2 <= 0.75:
driver.find_element_by_xpath("//a[@rel='q2_3']").click()
else:
driver.find_element_by_xpath("//a[@rel='q2_4']").click()

# 处理Q3
# 生成随机数,决定点哪个按钮
q3 = random()
if 0 <= q3 <= 0.25:
driver.find_element_by_xpath("//a[@rel='q3_1']").click()
elif 0.25 < q3 <= 0.50:
driver.find_element_by_xpath("//a[@rel='q3_2']").click()
elif 0.50 < q3 <= 0.75:
driver.find_element_by_xpath("//a[@rel='q3_3']").click()
else:
driver.find_element_by_xpath("//a[@rel='q3_4']").click()

# 处理Q4
# 生成随机数,决定点哪个按钮
q4 = random()
driver.find_element_by_xpath("//a[@rel='q4_1']").click()
driver.find_element_by_xpath("//a[@rel='q4_2']").click()
driver.find_element_by_xpath("//a[@rel='q4_3']").click()
driver.find_element_by_xpath("//a[@rel='q4_5']").click()
driver.find_element_by_xpath("//a[@rel='q4_7']").click()
if 0 <= q4 <= 0.15:
driver.find_element_by_xpath("//a[@rel='q4_4']").click()
elif 0.15 < q4 <= 0.30:
driver.find_element_by_xpath("//a[@rel='q4_6']").click()
elif 0.30 < q4 <= 0.45:
driver.find_element_by_xpath("//a[@rel='q4_8']").click()
elif 0.45 < q4 <= 0.60:
driver.find_element_by_xpath("//a[@rel='q4_9']").click()
elif 0.45 < q4 <= 0.60:
driver.find_element_by_xpath("//a[@rel='q4_10']").click()
else:
driver.find_element_by_xpath("//a[@rel='q4_11']").click()

# 处理Q5
# 生成随机数,决定点哪个按钮
q5 = random()
if 0 <= q5 <= 0.25:
driver.find_element_by_xpath("//a[@rel='q5_1']").click()
driver.find_element_by_xpath("//a[@rel='q5_2']").click()
driver.find_element_by_xpath("//a[@rel='q5_3']").click()
elif 0.25 < q5 <= 0.50:
driver.find_element_by_xpath("//a[@rel='q5_1']").click()
driver.find_element_by_xpath("//a[@rel='q5_2']").click()
driver.find_element_by_xpath("//a[@rel='q5_4']").click()
elif 0.50 < q5 <= 0.75:
driver.find_element_by_xpath("//a[@rel='q5_2']").click()
driver.find_element_by_xpath("//a[@rel='q5_3']").click()
driver.find_element_by_xpath("//a[@rel='q5_4']").click()
else:
driver.find_element_by_xpath("//a[@rel='q5_1']").click()
driver.find_element_by_xpath("//a[@rel='q5_2']").click()
driver.find_element_by_xpath("//a[@rel='q5_3']").click()
driver.find_element_by_xpath("//a[@rel='q5_4']").click()

# 处理Q6
# 生成随机数,决定点哪个按钮
q6 = random()
if 0 <= q6 <= 0.50:
driver.find_element_by_xpath("//a[@rel='q6_2']").click()
elif 0.50 < q6 <= 0.60:
driver.find_element_by_xpath("//a[@rel='q6_1']").click()
else:
driver.find_element_by_xpath("//a[@rel='q6_3']").click()

# 处理Q7
# 生成随机数,决定点哪个按钮
q7 = random()
if 0 <= q7 <= 0.95:
driver.find_element_by_xpath("//a[@rel='q7_1']").click()
elif 0.95 < q7 <= 0.98:
driver.find_element_by_xpath("//a[@rel='q7_2']").click()
else:
driver.find_element_by_xpath("//a[@rel='q7_3']").click()

# 处理Q8
# 生成随机数,决定点哪个按钮
q8 = random()
if 0 <= q8 <= 0.20:
driver.find_element_by_xpath("//a[@rel='q8_1']").click()
driver.find_element_by_xpath("//a[@rel='q8_2']").click()
driver.find_element_by_xpath("//a[@rel='q8_3']").click()
driver.find_element_by_xpath("//a[@rel='q8_4']").click()
elif 0.20 < q8 <= 0.40:
driver.find_element_by_xpath("//a[@rel='q8_1']").click()
driver.find_element_by_xpath("//a[@rel='q8_2']").click()
driver.find_element_by_xpath("//a[@rel='q8_3']").click()
driver.find_element_by_xpath("//a[@rel='q8_5']").click()
elif 0.20 < q8 <= 0.40:
driver.find_element_by_xpath("//a[@rel='q8_1']").click()
driver.find_element_by_xpath("//a[@rel='q8_2']").click()
driver.find_element_by_xpath("//a[@rel='q8_4']").click()
driver.find_element_by_xpath("//a[@rel='q8_5']").click()
elif 0.20 < q8 <= 0.40:
driver.find_element_by_xpath("//a[@rel='q8_1']").click()
driver.find_element_by_xpath("//a[@rel='q8_3']").click()
driver.find_element_by_xpath("//a[@rel='q8_4']").click()
driver.find_element_by_xpath("//a[@rel='q8_5']").click()
else:
driver.find_element_by_xpath("//a[@rel='q8_1']").click()
driver.find_element_by_xpath("//a[@rel='q8_2']").click()
driver.find_element_by_xpath("//a[@rel='q8_3']").click()
driver.find_element_by_xpath("//a[@rel='q8_4']").click()
driver.find_element_by_xpath("//a[@rel='q8_5']").click()

# 处理Q9
# 生成随机数,决定点哪个按钮
q9 = random()
driver.find_element_by_xpath("//a[@rel='q9_1']").click()
driver.find_element_by_xpath("//a[@rel='q9_3']").click()
driver.find_element_by_xpath("//a[@rel='q9_4']").click()
driver.find_element_by_xpath("//a[@rel='q9_5']").click()
driver.find_element_by_xpath("//a[@rel='q9_7']").click()
if 0 <= q9 <= 0.33:
driver.find_element_by_xpath("//a[@rel='q9_2']").click()
elif 0.33 < q9 <= 0.66:
driver.find_element_by_xpath("//a[@rel='q9_6']").click()
else:
driver.find_element_by_xpath("//a[@rel='q9_8']").click()

# 处理Q10
# 生成随机数,决定点哪个按钮
q10 = random()
driver.find_element_by_xpath("//a[@rel='q10_2']").click()
driver.find_element_by_xpath("//a[@rel='q10_4']").click()
if 0 <= q10 <= 0.50:
driver.find_element_by_xpath("//a[@rel='q10_3']").click()
else:
driver.find_element_by_xpath("//a[@rel='q10_1']").click()

# 处理Q11
# 生成随机数,决定点哪个按钮
q11 = random()
driver.find_element_by_xpath("//a[@rel='q11_1']").click()
driver.find_element_by_xpath("//a[@rel='q11_2']").click()
driver.find_element_by_xpath("//a[@rel='q11_3']").click()
if 0 <= q11 <= 0.25:
driver.find_element_by_xpath("//a[@rel='q11_4']").click()
elif 0.25 < q9 <= 0.50:
driver.find_element_by_xpath("//a[@rel='q11_5']").click()
elif 0.50 < q9 <= 0.75:
driver.find_element_by_xpath("//a[@rel='q11_6']").click()
else:
driver.find_element_by_xpath("//a[@rel='q11_7']").click()

# 处理Q12
# 生成随机数,决定点哪个按钮
q12 = random()
if 0 <= q12 <= 0.85:
driver.find_element_by_xpath("//a[@rel='q12_1']").click()
elif 0.85 < q12 <= 0.95:
driver.find_element_by_xpath("//a[@rel='q12_2']").click()
else:
driver.find_element_by_xpath("//a[@rel='q12_3']").click()

# 处理Q13
driver.find_element_by_xpath("//a[@rel='q13_1']").click()
driver.find_element_by_xpath("//a[@rel='q13_2']").click()
driver.find_element_by_xpath("//a[@rel='q13_3']").click()

# 模拟点击提交按钮
driver.find_element_by_xpath("//input[@value='提交']").click()
time.sleep(0.5)

# 模拟点击智能验证按钮
# 先点确认
driver.find_element_by_xpath("//button[text()='确认']").click()
# 再点智能验证提示框,进行智能验证
driver.find_element_by_xpath("//div[@id='captcha']").click()

上述代码亲测可用。

注意:当短时间内刷的问卷数过多时,可能会出现第二重智能验证,要拖动滑块进行验证,这个我暂时没有进行实验。

代码验证视频:
在这里插入图片描述

------------------本文已结束感谢阅读~------------------