前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >出于学习目的,我多填了几个问卷

出于学习目的,我多填了几个问卷

作者头像
做棵大树
发布2022-09-27 20:00:06
5190
发布2022-09-27 20:00:06
举报
文章被收录于专栏:代码日志

“为了填写 wj 星,我又拿起了 Python。 讲真,Python可做的 Java 也可以,不过主要在于 Java 的依赖生态不及 Python 完善,所以可能会更耗时一些,但是不代表 Java 比 Python 弱噢 ”

背景

学校发了个表单,让填写一下

分析历程

出于好奇和学习的心态,我想试下能不能自动填写表单;首先我想的是 JavaScript,因为毕竟是网页,所以首选的还是 JS,之后我创建了个 TEST 的表单进行测试,比较每次请求的路径与参数。

首先 WJ星 的页面里打开控制台后会进入 debug 模式,我们需要 deactivate 掉断点才可以继续操作。Firefox 操作后会造成页面卡死,伤心,我这么爱它它却让我去找 Chrome...

image-20210309221127176

错途

起初因为手速比较慢,只能拿到投票完之后的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? 一堆参数,如下所示

image-20210309220804399

其中的核心参数是 jqparam 以及 jqsign。具体怎么生成的呢?参考一篇52上的分析,走了一遍。

参考文章:对问卷星参数jqparam的分析和探索 https://www.52pojie.cn/forum.php?mod=viewthread&tid=1361387&highlight=%CE%CA%BE%ED%D0%C7 我这里就不再赘述了。

简言之就是使用插件重定向了 WJ星 远程访问的接口,然后本地去生成 jqparam,我试了试效果不大行。

那就手动自动吧

折腾完前边的之后发现走不过去,那就模拟点击吧~

于是我想到了 Selenium ,大家现在也都在上人工智能的课,不管听没听,至少电脑上都该有个Python的环境吧~

代码语言:javascript
复制
pip install selenium  # 下载selenium到本地

之后我们就有了基本,但是想要实现模拟点击,我们还需要下载浏览器驱动,Firefox 抛弃了我,所以只好下载 Chrome了。

驱动下载地址附上:http://chromedriver.storage.googleapis.com/index.html ,选择和自己浏览器大版本匹配的下载就可,下载解压后会得到一个 chromedriver.exe 复制到自己的Python安装目录下,这样默认就可以找到,不用再传参数了。

上边就绪后,我们就来对页面进行分析,有点类似于 Beautiful Soup

image-20210309222452929

然后分析页面,我们发现,问卷主体内容都在 id="ctl00_ContentPlaceHolder1_JQ1_question" 的 div 盒子下,于是我们确定了根节点。之后我们再看第一个问题的位置

image-20210309222729303

是在根目录下的 第二个div 下的 第一个fieldset 下的 第一个div ;然后我们定位一个问题的选项,是在再往下一级的 ulli 中。于是,我们有了定位的路径。

代码语言:javascript
复制
 selection1 = '//*[@id="ctl00_ContentPlaceHolder1_JQ1_question"]/div[2]/fieldset[1]/div[1]/div[2]/ul/li'

之后我们通过 webdriver.Chrome 来定位到 li ,我们发现实际上返回的是个列表

代码语言:javascript
复制
[<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() 操作,即可选中。

代码语言:javascript
复制
    answer_1 = driver.find_elements_by_xpath(selection1)[-1]
    answer_1.click()

其他选项同理,复选框也如此。最后我们选择提交即可。

以为到这里就结束了?我当时也这么觉得,但是我们在提交后会出现进行人机核验的弹窗,需要我们额外处理下,同时还需要处理下拖动滑块验证。

image-20210309223929604

在实践检验真理的时候,发现了问题所在 在进行智能验证时,WJ星会识别 Selenium!,看来人家早就料到了啊。

至于说怎么识别的呢?使用 selenium 的话,浏览器控制台会多出一个属性 window.navigator.webdriver 会变为 true,而当我们正常访问时它是 undefined 的。于是我们需要隐藏掉这个属性,新版本的Chrome (79以后的) 需要通过 js 来进行隐藏,具体代码放在下方

代码语言:javascript
复制
driver = Chrome('./chromedriver')
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
  "source": """
    Object.defineProperty(navigator, 'webdriver', {
      get: () => undefined
    })
  """
})

经过之后,这个表单终于可以提交了,先设置个次数?

代码语言:javascript
复制
for index in range(1, 200):

完整代码如下:

代码语言:javascript
复制
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()
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 做棵大树 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 分析历程
    • 错途
      • 那就手动自动吧
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档