学习python实现问卷星自动填写问卷

学习python实现问卷星自动填写问卷

任务一:找帖子

思路一:

配置环境:

slenium库,调用的对应浏览器驱动,此处为Chrome

解压后放在python目录下

使用python实现问卷星自动答题功能——基础篇

(对标签解析)

random库实现随机选择

定位题目对应标签

from selenium import webdriver
import random
打开问卷星
driver = webdriver.Chrome()
driver.get('https://www.wjx.cn/jq/22452252.aspx')

利用CSS选择器对页面进行解析

我们发现,我们所有的题目的回答的选项的标签都在li标签里面,所以我们找到li标签。ans=answer.find_elements_by_css_selector(‘li’)
####先滑到标签再去点击  
driver.execute_script("arguments[0].scrollIntoView();",answer)
### 找到标签
ans=answer.find_elements_by_css_selector('li')
lsans=random.choice(ans)
  lsans.click()

填空题:标签为textarea

`if not ans:
          text=answer.find_element_by_css_selector('textarea')
          text.send_keys('没有')
          continue`

提交问卷选项

am=driver.find_element_by_css_selector('#submit_button')
am.click()   

但是我们要想实现快速的填写,我们还得进行浏览器的关闭(因为浏览器开一次只能填一次,所以可以让它自动关闭),然后我们在使用一个循环,进行不断的开关浏览器,即可实现不停的填写问卷

driver.quit()

进一步:利用try catch跳过无法作答的题避免死循环

首先我们获得了answer之后,我们得避免一些问题导致我们的代码出现红字,于是我们使用try来避免报错(这个原因是,有些题目我们不能作答,但是使用死的代码会发生卡死的现象。)举个简单的例子,当我们遇到一个分叉的时候,比如有的题目,你选了否就会答第五题,选了是就会答第六题,这样子虽然我们会获取到五和六的题目的div,但是却不能两者都答,如果不使用try的话,会导致代码报错不能运行,我们使用try这样子就可以保持即使这题答不了,也只会把异常抛出,然后我们依然会往后做(这样子就从另一个角度来解决了分叉的问题)。

进一步:模拟滑动浏览器

因为问卷星肯定不是只有几题的,肯定是有很多道题的,所以我们要滑动浏览器(因为我们使用的点击只是模仿人的操作,人肯定是不能到自己看不到的地方答题的)使用driver.execute_script(“arguments[0].scrollIntoView();”,answer)来进行浏览器的滑动

思路一完整代码

from selenium import webdriver
import random
driver = webdriver.Chrome()
driver.get('https://www.wjx.cn/jq/22452252.aspx') 
answers = driver.find_elements_by_css_selector('.div_question')
for i in range(5):
    for answer in answers:
        try:
            ####先滑到标签再去点击
            driver.execute_script("arguments[0].scrollIntoView();",answer)
            ### 找到标签
            ans=answer.find_elements_by_css_selector('li')
            if not ans:
                text=answer.find_element_by_css_selector('textarea')
                text.send_keys('没有')
                continue
            lsans=random.choice(ans)
            lsans.click()
        except Exception as e:
            print(e)
    am=driver.find_element_by_css_selector('#submit_button')
    am.click()     
    driver.quit()
    
    

运行结果报错

第一次成功打开Chrome浏览器填写并退出,后台有提交记录

填写了单选和,后四次未执行成功

报错

MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=9659): Max retries exceeded with url: /session/14150baedf86c6930897efe3675806f3/element (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x00000204D3E95B70>: Failed to establish a new connection: [WinError 10061] 由于目标计算机积极拒绝,无法连接。'))

疑似解决办法1:解决连接未关闭

webdriver.chrome的get函数设置不了参数

selenium设置proxy、headers的方法(phantomjs、Chrome、Firefox)

这两种方法尝试解决失败:get方法不可以带参数

解决:

把打开浏览器并关闭改为关闭标签页

注:其中涉及了几个之前不了解的函数

# -*- coding: utf-8 -*-


from selenium import webdriver

import random

driver = webdriver.Chrome()

# driver = webdriver.Chrome(executable_path="C:/chromedriver.exe")
#安装目录不在python目录下解决办法

driver.get('https://www.baidu.com')
#打开一个主标签页


for i in range(5):

    js = "window.open('https://www.wjx.cn/jq/85695920.aspx')"
    #定义一个js语句传给driver.execute_scrip执行:打开新标签页

    driver.execute_script(js)

    # driver.get('https://www.wjx.cn/jq/22452252.aspx') 

    handlers =driver.window_handles

    driver.switch_to_window(handlers[1])

    answers = driver.find_elements_by_css_selector('.div_question')

    for answer in answers:

        try:

            ####先滑到标签再去点击

            driver.execute_script("arguments[0].scrollIntoView();",answer)

            ### 找到标签

            ans=answer.find_elements_by_css_selector('li')

            if not ans:

                text=answer.find_element_by_css_selector('textarea')

                text.send_keys('没有')

                continue

            lsans=random.choice(ans)

            lsans.click()

        except Exception as e:

            print(e)

    # am=driver.find_element_by_css_selector('#submit_button')

    # am.click()    

    driver.close()

    driver.switch_to_window(handlers[0])

driver.quit()

思路2

2018年4.28;可能已经失效,包加密了

创建测试问卷,提交,查看向服务器发送的包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nzP9oyOv-1595145819599)(F:\笔记\笔记图\爬虫思路2_01.jpg)]

向一个地址发送了:

  • 问卷id curlD
  • 发送时间 t
  • 开始答题时间 starttime
  • 未知参数: rn
  • 题目答案 submitdata

那模拟提交问卷的思路也就很清晰了

  1. 请求页面 就解析出(rn)
  2. 计算其他参数,如t、starttime
  3. 找到所有的问题,并随机做答,构造submitdata
  4. 发送请求

具体代码

最主要的就两个部分

找到 rn

def parse_post_url(resp):
    '''
    解析出提交问卷的url
    '''
    # 找到rn
    rn = int(resp.html.search('rndnum="{}"')[0].split('.')[0])
    # 提交问卷的时间
    raw_t = round(time.time(), 3)
    t = int(str(raw_t).replace('.', ''))
    # 模拟开始答题时间
    starttime = datetime.fromtimestamp(
        int(raw_t) - randint(1, 60 * 3)).strftime("%Y/%m/%d %H:%M:%S")

    url = POST_URL_MAP.format(QUESTION_ID, t, starttime, rn)
    return url

找到所有题目

def parse_post_data(resp):
    '''
    解析出问题和选项
    返回post_data
    '''
    post_data = {'submitdata': ""}
    questions = resp.html.find('fieldset', first=True).find('.div_question')

    for i, q in enumerate(questions):
        title = q.find('.div_title_question_all', first=True).text
        choices = [t.text for t in q.find('label')]
        random_index = randint(0, len(choices) - 1)
        choice = choices[random_index]
        post_data['submitdata'] += '{}${}}}'.format(i+1, random_index+1)
        print(QUESTION_INFO.format(title, choices, choice))
        time.sleep(0.5)
    # 去除最后一个不合法的`}`
    post_data['submitdata'] = post_data['submitdata'][:-1]
    return post_data

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BwDXBydc-1595145819602)(F:\笔记\笔记图\爬虫思路2_02.jpg)]

反馈:

  • 代码现在不能用了啊,post返回的也是200,但是问卷星后台不统计啊,
  • 同一个ip多次填写不会触发验证码麽?
  • 使用代理ip呀

猜你喜欢

转载自blog.csdn.net/qq_44274233/article/details/107446667