引言
问卷星可以说是当下使用最广泛的问卷收集平台, 即使你没有使用它发布过问卷, 相信你也看到过朋友圈四处求人填问卷的苦bi朋友, 作为新时代的青年, 我们不禁提出疑问: 这样的问卷真的需要手动填写吗? 能不能利用工具简化操作呢?
如果你也是一个好奇宝宝, 不妨和作者一起作者来一场轰轰烈烈的试验.
注意: 本文中出现的所有技术手段都是从技术角度出发对平台进行的测试行为, 请勿滥用
技术路线
由于问卷星是一个web问卷平台, 不难想到使用web自动化库来模拟点击来完成, 于是我们使用python
下非常受欢迎的selenium
库来实现.
接下来简单聊聊selenium
的基本用法:(熟悉selenium
的读者可以跳过)
selenium
在python中最基本的用法是
from selenium import webdriver
url = 'https://www.example.com'
driver = webdriver.Chrome()
driver.get(url)
上面的代码会打开一个受脚本控制的浏览器, 并跳转到我们给出的url
.
这里以Chrome为例, 实际上 firefox 等其他浏览器也没问题.
以此为基础, 之后我们之后所有对浏览器的操作都是通过操作创建出的driver
对象来实现的.
那么之后的思路就很清晰了, 在填写问卷的过程中, 实际上只有对按钮的点击操作和对文本框的填写操作, 通过click()
和send_key()
可以轻松解决.
一脚下去全是坑 – 哪有那么简单
常言道:“Talk is cheep, show me the code.”
在实际上手中我们发现, 虽然思路很简单, 但是遇到的问题可真不少.
首先我们先验证思路的可行性.
初步验证
我们打开一个问卷, 尝试在python
的命令行中实现对按钮的点按和文本框的填写
clickItem = '...'
driver.find_element(By.XPATH, clickItem).click # 点击找到的
driver.find_element(By.ID, 'qn').send_key("text") # 输入文字
经检验, 我们发现这确实能点击题目中的选项, 以及填写文字, 芜湖起飞!!!
问题1 – 多次点击后程序崩溃
首先, 为了方便, 我们在此处为单选和多选分别封装了函数.
简单起见我们先看单选:
def SingleChoiceQuestion(driver, qNumber, choices, weights):
random_choice = weighted_random_choice(
choices, weights)
clickItem = r'//input[@id="q' + str(qNumber) + \
'_' + random_choice + r'"]/following-sibling::a'
driver.find_element(By.XPATH, clickItem).click()
看起来天衣无缝了 : )
然而当我们把相同的逻辑用于多选, 我们发现经常出现无法点击导致崩溃程序崩溃的情况.
为什么呢?
首先合理怀疑我们操作的太快网页来不及反应, 于是在click
之前加上
time.sleep(0.5)
填写的速度明显变慢了, 但是问题依然没有改善.
作为一个熟练的脚本小子, 我们马上打开浏览器…
首先映入眼帘的方法是添加显式等待
WebDriverWait(driver, 3).until(
EC.element_to_be_clickable((By.XPATH, clickItem))).click()
然而实践发现并没有什么用… ¯_(ツ)_/¯
看到有帖子说将click
改为enter
可以解决, 但是… ¯_(ツ)_/¯
经过不懈尝试, 终于, 在我的环境下, 可以运行的方案是:
btm = driver.find_element(By.XPATH, clickItem)
driver.execute_script('arguments[0].click();', btm)
然而这不是结束, 解决了库的问题后, 真正的问题才刚刚暴露出来.
问题2 - 人机验证按钮
刚填了没几张, 新的问题来喽…
问卷星在我们提交之后要求我们安吉按钮通过人机验证.
不就是点一下吗?
小小按钮, 我还拿捏不了你了???
我们只需要定位到按钮, 同样以sendkey的方式点击一下…
然而, 验证失败. emm, 看来还有鬼…
还要检测参数???
又是一轮查找资料…
我们最终发现问卷星还会检测浏览器参数, 如果发现是driver一律拦截.
那么反其道而行之, 我们有了下面的代码:
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
chrome_options.add_experimental_option(
'excludeSwitches', ['enable-automation'])
chrome_options.add_experimental_option('useAutomationExtension', False)
还是不行???
还是验证失败.
这时为什么呢?
处于好奇, 要不手动点击一下?
哦?! 可以了!
那这样就简单了. (~ ̄▽ ̄)~
那么我们只要使用系统级工具点击一下不就行了?
说干就干, 由于我们在linux平台, 我们使用ydotool
来实现.
os.system('ydotool mousemove -a -x 1540 -y 202')
time.sleep(0.5)
os.system('ydotool click 0x00')
点击没反应?
这又是什么问题.
手动点击可以, 用工具click
就不行? 工具和手动操作有什么区别呢?
经过思考, 似乎工具click
和手动点击的区别在按下的时间?
沿这个思路我们优化一下代码,
os.system('ydotool mousemove -a -x 1540 -y 202')
time.sleep(0.5)
# os.system('ydotool click 0x00')
os.system('ydotool click 0x40')
time.sleep(0.5)
os.system('ydotool click 0x80')
终于可以了…
经过这一通折腾, 脚本总算是跑起来…
第二道验证
当我们在短时间内填写大量问卷后, 问卷星会刷新出第二道验证, 也就是在点击按钮之后套拖动滑块才能提交.
由于我们使用了模拟鼠标操作的工具, 相信绕过它的方式也差不多, 这里不再赘述, 如果你有兴趣, 可以自己尝试一下, 不要忘了把成果放在评论区和大家一起分享哦.