iT邦幫忙

0

用JavaScript取得Google表單的作答內容

  • 分享至 

  • xImage
  •  

情境分析

最近遇到老師用Google表單給了考古題,但是答案要自己找的作業,裡面題目也沒有附題號,所以如果寫完題目後按提交,就不知道自己到底寫了啥不能複習(也不能跟同學對答案

於是,我就想要一個可以快速匯出我在Google表單填的資料的方法,假設表單只有一頁,可能是大量的單選題。


最初的想法

說到這裡,想想大概就是用js,在console印出來是最簡單暴力的,所以第一個被我找到的是jQuery的serializeArray(),這個以前也有人討論過(參考資料)
只要找到form元素的id,jQuery就幫你表單的所有input的value匯整到一個陣列裡了,前提是要自己引入jQuery,於是我就迅速寫了以下js掛到console上:

var s = "";
var formId = "mG61Hd"; //表單元素id
var qNumbers = 50;
var ansArray = $("#"+formId).serializeArray();
for (var i = 0; i < qNumbers ;i++) {
	s += (i+1) + ":";
	s += ansArray[i]["value"];
	s += "\n";
}
console.log(s);

誰知道後來發現只有我能用,同學匯出竟然都是亂序的這樣就對不了答案了,才知道似乎是Google表單在儲存草稿,重新整理後,每個input的name裡面的序號會重新打亂,最後serializeArray()照name排列出來的順序就是亂的,而我是網頁一直開著沒有重整。

好吧,那只好認真花點時間來研究...

後記(雪上加霜):本來引入jQuery我會暴力地找個CDN,把整個js檔內容複製貼到cosole執行,就完成腳本的載入了,後來我寫文章的時候發現Google Form更新過,用了TrustedHTML(簡單來說就是一個白名單讓我沒辦法輕易地載入外來腳本),所以這個方法就真的失效了(除非哪天我知道可以怎麼繞過)
https://ithelp.ithome.com.tw/upload/images/20230729/20140925PnSjaYWviM.png


認真一回

認真看了幾眼前端程式,我找到"FB_PUBLIC_LOAD_DATA_"這個變數,裡面有表單名稱,網址等等,有所有題目和其序號的對照在FB_PUBLIC_LOAD_DATA_[1][1]裡。
所以邏輯如下:

  1. FB_PUBLIC_LOAD_DATA_[1][1][題號][4][0][0]得到每題的專屬序號(identifier)
  2. 蒐集整個表單的所有input元素
  3. 遍歷找到剛剛取得的序號的input元素,得到他的value,就是我們填寫的答案
  4. 現在我們有了對應的題號,作答內容,甚至有題目(在FB_PUBLIC_LOAD_DATA_[1][1][題號][1]),就可以輸出想要的結果了
  • 值得一題的是,FB_PUBLIC_LOAD_DATA_[1][1]裡面的順序不會因為表單的隨機決定問題順序設定打亂,匯出的順序每個人每一次還是會一樣

初步寫的程式:

var formId = "mG61Hd"; // 表單ID
var form = document.getElementById(formId); // 獲取表單元素
var shuffledAns = form.getElementsByTagName("input"); // 獲取所有input元素
var result = "";
FB_PUBLIC_LOAD_DATA_[1][1].forEach((question, QNumber) => {
  var sortedId = question[4][0][0]; // 記錄序號的位置
  for (var i = 0; i < shuffledAns.length; i++) {
    if (shuffledAns[i].name == "entry." + sortedId) {
      result += QNumber + 1 + ":";
      result += shuffledAns[i].value;
      result += "\n";
    }
  }
});
console.log(result);

試著用些進階點的語法:

//google表單印出優化版
var formId = "mG61Hd"; // 表單ID
var shuffledAns = document.getElementById(formId).getElementsByTagName("input"); // 獲取表單中所有的input元素
var result = "";
FB_PUBLIC_LOAD_DATA_[1][1].forEach((element, questionNumber) => {
  var sortedId = element[4][0][0]; // 記錄序號的位置
  Array.prototype.some.call(shuffledAns, (element) => {
    var findAns = element.name == "entry." + sortedId;
    if (findAns) {
      result += questionNumber + 1 + ":";
      result += element.value;
      result += "\n";
    }
    return findAns; // 找到答案時返回true,讓some()結束遍歷
  });
});
console.log(result);

輸出結果:
https://ithelp.ithome.com.tw/upload/images/20230729/201409255K9MaUgZFy.png

可惜下面的參考資料再我寫完後才找到的,也許就能省下點時間,但他分析的更完整,也有介紹非單選題以外的答案怎麼判斷和取得,有興趣的可以參考看看

參考資料

https://theconfuzedsourcecode.wordpress.com/2019/12/15/programmatically-access-your-complete-google-forms-skeleton/


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言