基於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 的一些功能開發出來的非官方版本。--(https://blog.csdn.net/freeking101/article/details/93331204)
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自帶的功能實現腳本定時運行。
參考
https://blog.csdn.net/weixin_44632570/article/details/112444096