飞道的博客

python问卷星模拟提交

352人阅读  评论(0)

*一、前言

**
笔者在家闲得无聊,突然想突破一下问卷星的反爬虫机制,顺便刷刷问卷,于是就开始分析了。
**

二、分析过程

**
1、fiddler抓包
模拟提交首先当然是打开fiddler看看提交了什么包啦。

2、分析不变参数
我们先来看不变的参数,这样的话我们把它作为一个常量就可以了。经过多次提交之后发现,submittype(答卷类型?),curID(答卷ID),rn(一个随机数random,但是在同一份问卷中是固定的),hlv(这个猜不出来)
3、分析变量
1、t参数
提交结束时间,因为这个时间总是比starttime晚,而且转化为时间戳就是一个具体的时间。
2、starttime参数
开始时间,见名知意,调查问卷也统计这个参数
3、ktimes
这个一开始也是百思不得其解,后来在提交按钮的Event Listeners的click事件中找到了ktimes关键字

在这个js文件中,ktimes被做了多次自增运算,我怀疑就是故意来坑刷题的人。(▼ヘ▼#),但是最后我直接放了一个随机数好像就蒙混过关了。。。
4、jqnonce参数
这个参数在问卷页面直接搜索关键字直接可以搜到,利用正则表达式截取就可以了。
5、jqsign参数
我更加加深了我的怀疑,这个参数也是故意来坑刷题的人的。他先是做了代码混淆,然后又做了一个莫名其妙的运算。。不过还好我为什么要和他硬碰硬呢?直接利用python库执行js代码,绕开他的签名算法。

三、网站的反爬措施

 暂时知道的有两个吧,一个是单IP提交30次左右直接标记为可疑IP,填问卷的时候疯狂弹验证码,解决这个问题我用了代理IP。另一个是不同IP20秒内提交11次左右问卷被标记为可疑问卷,此时所有填写IP都会疯狂弹验证码,解决这个问题我用了程序sleep的方式来使问卷退出黑名单。

四、代码如下

import random
import time
import requests
import urllib3
import execjs
import re

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
requests.adapters.DEFAULT_RETRIES = 5
TARGET_URL = 'https://www.wjx.cn/jq/***.aspx'
headers = {
    'Connection': 'keep-alive',
    'Content-Length': '24',
    'Origin': 'https://www.wjx.cn',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Accept': '*/*',
    'Referer': TARGET_URL,
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Cookie':'*****'
}

# 代理服务器
proxies = {
    "http": proxyMeta,
    "https": proxyMeta,
}

main_session = requests.session()
def get_jqnonce():
    response = requests.get(TARGET_URL, verify=False, timeout=5)
    html_text = response.text
    jq_list = re.findall('jqnonce.*";', html_text)
    jq_value = jq_list[0].split('"')
    time_list = re.findall('starttime.*";', html_text)
    time_value = time_list[0].split('"')
    return jq_value[1], time_value[1]
    
def get_jqsign(jqnonce, ktimes):
    jsencrpt = """
        function dataenc(a,ktimes) 
            {
                var c, d, e, b = ktimes % 10;
                for (0 == b && (b = 1), c = [], d = 0; d < a.length; d++) e = a.charCodeAt(d) ^ b, c.push(String.fromCharCode(e));
                return c.join("")
            }
        """
    jsfunc = execjs.compile(jsencrpt)
    jqsign = jsfunc.call('dataenc', jqnonce, ktimes)
    return jqsign


submittype = '1'
curID = re.findall('/[0-9]+', TARGET_URL)[0].replace('/', '')
(jqnonce, starttime) = get_jqnonce()
timeArray = time.strptime(starttime, "%Y/%m/%d %H:%M:%S")
rn = '1739566547'
hlv = '1'
print('--------------开始提交--------------------')
for i in range(0, 100):
    t = str(int(time.mktime(timeArray)) + random.randint(5, 30)) + str(random.randint(100, 999))  #模拟作答时间,同时补齐时间戳
    ktimes = random.randint(10, 100)
    jqsign = get_jqsign(jqnonce, ktimes)
    payload = {
        'submittype': submittype,
        'curID': curID,
        'starttime': starttime,
        't': t,
        'rn': rn,
        'hlv': hlv,
        'ktimes': ktimes,
        'jqnonce': jqnonce,
        'jqsign': jqsign
    }
    submitdata = {'submitdata': '1$' + str(random.randint(1, 2)) + '}2$' + str(random.randint(1, 2))}  #作答结果随机
    response = main_session.post('https://www.wjx.cn/joinnew/processjq.ashx', verify=False, params=payload,
                                 data=submitdata,
                                 headers=headers, proxies=proxies)
    main_session.keep_alive = False
    print(response.text)
    if re.findall('^7', response.text):
        print('发现验证码,我要睡一会')
        time.sleep(20)
        print('我醒了')
    print(f'提交到第{i}次')
print('--------------提交结束--------------------')

五、存在问题

首先还是效率比较慢,因为要长时间sleep而且没有采取协程或者多线程,还有就是存在一个严重的问题,header必须强制加入cookie否则会报错误,这个我很纳闷,我之前用第一次请求来传cookie竟然失效了,这个问题希望大佬可以解决一下。以及有其他问题都可以指出来,欢迎技术交流。


转载:https://blog.csdn.net/weixin_43913097/article/details/105474161
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场