学习python实现问卷星自动填写问卷
文章目录
任务一:找帖子
思路一:
配置环境:
slenium库,调用的对应浏览器驱动,此处为Chrome
解压后放在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
那模拟提交问卷的思路也就很清晰了
- 请求页面 就解析出(rn)
- 计算其他参数,如t、starttime
- 找到所有的问题,并随机做答,构造submitdata
- 发送请求
具体代码
最主要的就两个部分
找到 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呀