学校思政实践要收集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: 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" 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_survey = ("https://www.wjx.cn/xx/xxxxxxx.aspx") 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 = random() if 0 <= q1 <= 0.5: driver.find_element_by_xpath("//a[@rel='q1_1']").click() else: driver.find_element_by_xpath("//a[@rel='q1_2']").click()
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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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()
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()
|
上述代码亲测可用。
注意:当短时间内刷的问卷数过多时,可能会出现第二重智能验证,要拖动滑块进行验证,这个我暂时没有进行实验。
代码验证视频: