为了填写 WJ 星,我又拿起了 Python。
讲真,Python 可做的 Java 也能够,不过次要在于 Java 的依赖生态不迭 Python 欠缺,所以可能会更耗时一些,然而不代表 Java 比 Python 弱噢
背景
学校发了个表单,让填写一下
剖析历程
出于 好奇和学习 的心态,我想试下能不能主动填写表单;首先我想的是 JavaScript,因为毕竟是网页,所以首选的还是 JS,之后我创立了个 TEST 的表单进行测试,比拟每次申请的门路与参数。
首先 WJ 星 的页面里关上控制台后会进入 debug 模式,咱们须要 deactivate 掉断点才能够持续操作。Firefox 操作后会造成页面卡死,伤心,我这么爱它它却让我去找 Chrome…
错途
起初因为手速比较慢,只能拿到投票完之后的 url:https://www.wjx.cn/wjx/join/complete.aspx?activityid=109478233&joinid=108761857258&sojumpindex=1&comsign=135A7EC8CFEF9AFBE716B45BC4422FF56E5CB4F0&s=&njqj=1
;通过屡次比对,发现其中的 joinid
comsign
两个字段会发生变化,我认为这个对上后会发现生成所依赖的接口或者文件,这样之后通过生成这两个字段,循环就能重复刷票了。
起初发现自己 too simple 了,这条接口基本改不了投票的后果,也就是不作数!
之后进步手速,拿到了发送申请的接口地址:https://www.wjx.cn/joinnew/processjq.ashx? 一堆参数
,如下所示
其中的外围参数是 jqparam
以及 jqsign
。具体怎么生成的呢?参考一篇 52 上的剖析,走了一遍。
参考文章:对问卷星参数 jqparam 的剖析和摸索 https://www.52pojie.cn/forum…. 我这里就不再赘述了。
简言之就是应用插件重定向了 WJ 星 近程拜访的接口,而后本地去生成 jqparam,我试了试成果不大行。
那就手动主动吧
折腾完前边的之后发现走不过去,那就模仿点击吧~
于是我想到了 Selenium
,大家当初也都在上人工智能的课,不论听没听,至多电脑上都该有个 Python 的环境吧~
pip install selenium # 下载 selenium 到本地
之后咱们就有了根本,然而想要实现模仿点击,咱们还须要下载浏览器驱动,Firefox 摈弃了我,所以只好下载 Chrome 了。
驱动下载地址附上:http://chromedriver.storage.g…,抉择和本人浏览器大版本匹配的下载就可,下载解压后会失去一个 chromedriver.exe
复制到本人的 Python 装置目录下,这样默认就能够找到,不必再传参数了。
上边就绪后,咱们就来对页面进行剖析,有点相似于 Beautiful Soup
了
而后剖析页面,咱们发现,问卷主体内容都在 id="ctl00_ContentPlaceHolder1_JQ1_question"
的 div 盒子下,于是咱们确定了根节点。之后咱们再看第一个问题的地位
是在根目录下的 第二个 div
下的 第一个 fieldset
下的 第一个div
;而后咱们定位一个问题的选项,是在再往下一级的 ul
的 li
中。于是,咱们有了定位的门路。
selection1 = '//*[@id="ctl00_ContentPlaceHolder1_JQ1_question"]/div[2]/fieldset[1]/div[1]/div[2]/ul/li'
之后咱们通过 webdriver.Chrome
来定位到 li
,咱们发现实际上返回的是个列表
[<selenium.webdriver.remote.webelement.WebElement (session="93b4af8577a5b18396ea581abaa417ca", element="3ddfb20d-a1ef-4811-b49d-d50f70ab992f")>, <selenium.webdriver.remote.webelement.WebElement (session="93b4af8577a5b18396ea581abaa417ca", element="7db65e3e-2779-4180-be83-669ac2db1192")>]
咱们取出最初一个,而后执行 click()
操作,即可选中。
answer_1 = driver.find_elements_by_xpath(selection1)[-1]
answer_1.click()
其余选项同理,复选框也如此。最初咱们抉择提交即可。
认为到这里就完结了?我过后也这么感觉,然而咱们在提交后会呈现进行人机核验的弹窗,须要咱们额定解决下,同时还须要解决下拖动滑块验证。
在实际测验真谛的时候,发现了问题所在 在进行智能验证时,WJ 星会辨认 Selenium!,看来人家早就料到了啊。
至于说怎么辨认的呢?应用 selenium 的话,浏览器控制台会多出一个属性 window.navigator.webdriver
会变为 true
,而当咱们失常拜访时它是 undefined
的。于是咱们须要暗藏掉这个属性,新版本的 Chrome (79 当前的) 须要通过 js 来进行暗藏,具体代码放在下方
driver = Chrome('./chromedriver')
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """Object.defineProperty(navigator,'webdriver', {get: () => undefined
})
"""
})
通过之后,这个表单终于能够提交了,先设置个次数?
for index in range(1, 200):
残缺代码如下:
import time
import random
from selenium import webdriver
from selenium.webdriver import ChromeOptions
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
def autoFinishForm():
# 将问卷星网站放在上面
driver.get(' 群里的投票地址)
# 单选题 1
selection1 = '//*[@id="ctl00_ContentPlaceHolder1_JQ1_question"]/div[2]/fieldset[1]/div[1]/div[2]/ul/li'
# print("log driver.find_elements_by_xpath(selection1):", driver.find_elements_by_xpath(selection1));
answer_1 = driver.find_elements_by_xpath(selection1)[-1]
answer_1.click()
# 单选题 2
selection2 = '//*[@id="ctl00_ContentPlaceHolder1_JQ1_question"]/div[2]/fieldset[1]/div[2]/div[2]/ul/li'
answer_2 = driver.find_elements_by_xpath(selection2)[-1]
answer_2.click()
# 单选题 3
selection3 = '//*[@id="ctl00_ContentPlaceHolder1_JQ1_question"]/div[2]/fieldset[1]/div[3]/div[2]/ul/li'
answer_3 = driver.find_elements_by_xpath(selection3)[-1]
answer_3.click()
# 提交按钮
submit = driver.find_elements_by_id('submit_button')[0]
submit.click()
# 提交后的验证弹窗
alterPath = '//*[@id="alert_box"]/div[2]/div[2]/div[2]/button'
checkButton = driver.find_elements_by_xpath(alterPath)[0]
checkButton.click()
# 智能验证按钮
captchaout = '//*[@id="captchaout"]/div[1]'
captchaoutBtn = driver.find_elements_by_xpath(captchaout)[0]
captchaoutBtn.click()
time.sleep(3)
# 拖动滑块的反向操作:关掉再点 SM_POP_CLOSE_1
# closeslipper = '//*[@id="submit_div"]/div[1]/div[1]/div[1]/div[2]/div[1]/div[1]/div[1]/span'
# closeslipperBtn = driver.find_elements_by_xpath(closeslipper)[0]
closeslipperBtn = driver.find_elements_by_xpath("//div[@id='SM_POP_CLOSE_1'and @class='sm-pop-close']")[0]
closeslipperBtn.click()
captchaoutBtn.click()
time.sleep(3)
driver.quit()
if __name__ == '__main__':
# 循环 200 次
for index in range(1, 200):
driver = webdriver.Chrome(options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """Object.defineProperty(navigator,'webdriver', {get: () => undefined
})
"""
})
autoFinishForm()
关注 做棵大树,查看更多好玩的事儿