基于python的问卷星自动填写脚本
引言
疫情期间,总有许多的问卷星需要填写,大多数都是单一内容的重复输入。为了更好地学习(摸鱼),研究了一下问卷星自动填写的方法。
思路历程
selenium
说到网络爬虫,很容易就想到了selenium。作为一个知名的web自动化测试框架,selenium在爬虫中应用广泛。那么首先尝试采用selenium进行操作。
'''
Description: 问卷星自动签到 selenium
'''
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('网站')
driver.find_element_by_id('q1').send_keys('姓名')
driver.find_element_by_id('q2').send_keys('学号')
driver.find_element_by_xpath('/html/body/div[4]/div[2]/div[2]/div[1]/div/div[1]/div[2]/div[2]/fieldset/div[3]/div[2]/ul/li[2]/a').click()
driver.find_element_by_xpath('/html/body/div[4]/div[2]/div[2]/div[1]/div/div[1]/div[2]/div[2]/fieldset/div[4]/div[2]/ul/li[2]/a').click()
driver.find_element_by_xpath('/html/body/div[4]/div[2]/div[2]/div[1]/div/div[1]/div[2]/div[2]/fieldset/div[5]/div[2]/ul/li[3]/a').click()
driver.find_element_by_xpath('/html/body/div[4]/div[2]/div[2]/div[1]/div/div[1]/div[2]/div[2]/fieldset/div[6]/div[2]/ul/li[1]/a').click()
driver.find_element_by_xpath('/html/body/div[4]/div[2]/div[2]/div[1]/div/div[1]/div[2]/div[2]/fieldset/div[7]/div[2]/ul/li[3]/a').click()
driver.find_element_by_id("submit_button").click()
time.sleep(0.5)
driver.quit()
element的获取方法有id/class/xpath
,一般选择class和id,也可以用xpath对element进行精确定位(firefox自带获取xpath/cssSelector
的选项卡)。然而提交的时候确出现了问题,这种方法会被要求进行验证,并且验证无法成功。其原因就在于问卷星对selenium进行了检测,因此这个方法PASS。
selenium 的缺点很明显,比如速度太慢、对版本配置要求严苛,最麻烦是经常要更新对应的驱动。还有些网页是可以检测到是否是使用了selenium 。并且selenium 所谓的保护机制不允许跨域 cookies 保存以及登录的时候必须先打开网页然后加载 cookies 再刷新的方式很不友好。
pyppeteer
于是就发现了这款web 自动化测试工具 pyppeteer,虽然支持的浏览器比较单一,但在安装配置的便利性和运行效率方面都要远胜 selenium。介绍 Pyppeteer 之前先说一下 Puppeteer,Puppeteer 是 Google 基于 Node.js 开发的一个工具,主要是用来操纵 Chrome 浏览器的 API,通过 Javascript 代码来操纵 Chrome 浏览器的一些操作,用作网络爬虫完成数据爬取、Web 程序自动测试等任务,其 API 极其完善,功能非常强大。 Pyppeteer 实际上是 Puppeteer 的 Python 版本的实现,是一位来自于日本的工程师依据 Puppeteer 的一些功能开发出来的非官方版本。--()
Pyppeteer 两大特点:chromium浏览器和asyncio框架(Python的一个异步协程库)。由于 Pyppeteer 是基于 asyncio 构建的,它的所有属性和方法 几乎都是coroutine (协程)对象,因此在构建异步程序的时候非常方便,天生就支持异步运行。
'''
Description: 问卷星自动签到 pyppeteer
'''
import asyncio
from pyppeteer import launch
from pyppeteer_stealth import stealth # 反爬虫第三方库
async def main():
browser = await launch({
'executablePath': 'C:\Program Files\Google\Chrome\Application\chrome.exe',
# Pyppeteer 默认使用的是无头浏览器,所以要显示需要给False
'headless': False,
'args': ['--no-sandbox', '--window-size=1366,850']
})
page = await browser.newPage()
await page.setViewport({'width':1366,'height':768})
# 防止页面识别出脚本(反爬虫关键语句)
await stealth(page)
await page.goto('网页')
# 填空题:page.type(selector,text),在指定selector的元素上填写text
await page.type('#q1', '李四') # CssSelector
await page.type('#q2', '学号')
# 单选题:先用page.querySelector(selector)找到指定的元素,再调用元素的click()方法、还可以用xpath方法
# CssSelector: ul在第二个次序、li在第二个次序、a标签在第二个次序
button = await page.querySelector('#divquestion3 > ul:nth-child(2) > li:nth-child(2) > a:nth-child(1)')
await button.click()
button = await page.querySelector('#divquestion4 > ul:nth-child(2) > li:nth-child(2) > a:nth-child(1)')
await button.click()
button = await page.querySelector('#divquestion5 > ul:nth-child(2) > li:nth-child(3) > a:nth-child(1)')
await button.click()
button = await page.querySelector('#divquestion6 > ul:nth-child(2) > li:nth-child(1) > a:nth-child(1)')
await button.click()
button = await page.querySelector('#divquestion7 > ul:nth-child(2) > li:nth-child(3) > a:nth-child(1)')
await button.click()
# # 地址题:先点击手动填写地址,再在地址框内填写相应地址
# address = await page.querySelector("#divquestion7 > ul > li:nth-child(1) > label")
# await address.click()
# await page.type('#q9', '地址')
# # 日期选择题:先点击日期选择框,在出现的iframe寻找元素并调用click()方法
# date1 = await page.querySelector("#q4")
# await date1.click()
# frame = page.frames
# date2 = await frame[1].querySelector('#selectTodayButton')
# await date2.click()
# 找到提交按钮提交
submit = await page.querySelector('#submit_button')
await submit.click()
await asyncio.sleep(2)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
# 反爬虫:原理是将get请求转换成undefined, 也可以用stealth库来防止机器人检测
await stealth(page)
await page.evaluateOnNewDocument('Object.defineProperty(navigator, "webdriver", {get: () => undefined})')
# 三种解析方式
Page.querySelector() # CSS选择器
Page.querySelectorAll()
Page.xpath() # xpath
page.evaluate('window.scrollBy(0, window.innerHeight)') # 执行js语句
# Pyppeteer的evaluate()方法只使用JavaScript字符串,该字符串可以是函数或表达式。可以添加选项force_expr=True,强制Pyppeteer作为表达式处理。
总结
- selenium和pyppeteer都是一种web自动化测试工具,其中pyppeteer提供了防机器人检测的功能。
- 如果用于大量问卷的填写,会出现更多复杂的验证方式,本文仅仅图一乐。
- 此后还可以通过windows自带的功能实现脚本定时运行。