Extract MCQs

Extract MCQs from the webpage

当前为 2024-02-26 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Extract MCQs
// @namespace    themrsami
// @version      2.0
// @description  Extract MCQs from the webpage
// @author       You
// @match        http://*/*
// @match        https://*/*
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Add some CSS for the button
    GM_addStyle(`
        #extract-mcqs-button {
            position: fixed;
            bottom: 20px;
            right: 20px;
            padding: 10px 20px;
            font-size: 16px;
            color: white;
            background-color: #007BFF;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            z-index: 9999;
        }
        #extract-mcqs-button:hover {
            background-color: #0056b3;
        }
    `);

    // Create the button
    let button = document.createElement('button');
    button.id = 'extract-mcqs-button';
    button.innerText = 'Extract MCQs';
    document.body.appendChild(button);

GM_registerMenuCommand('Extract MCQs', function() {
// Remove elements that destroy the structure
let elementsToRemove = [
    ...document.querySelectorAll('div[style="margin:30px 0px;"]'),
    ...document.querySelectorAll('div.sf-mobile-ads'),
    ...document.querySelectorAll('div.sf-desktop-ads'),
    ...document.querySelectorAll('span.collapseomatic')
];

for (let element of elementsToRemove) {
    if (element.parentNode) {
        element.parentNode.removeChild(element);
    }
}

let pTags = document.getElementsByTagName('p');
let results = [];

for (let i = 0; i < pTags.length; i++) {
    let imgHref = null;
    let aTag = pTags[i].getElementsByTagName('a')[0];
    if (aTag) {
        let imgTag = aTag.getElementsByTagName('img')[0];
        if (imgTag) {
            imgHref = imgTag.src || imgTag.getAttribute('data-src');
            aTag.parentNode.removeChild(aTag);
        }
    }

    let startsWithNumber = /^\d/.test(pTags[i].textContent);
    let nextSibling = pTags[i].nextElementSibling;
    if (startsWithNumber && nextSibling && nextSibling.tagName.toLowerCase() === 'div' && nextSibling.classList.contains('collapseomatic_content')) {
        let statementAndOptions = pTags[i].innerHTML.split('<br>');
        let statement = statementAndOptions.shift();
        let options = statementAndOptions.join('<br>').replace(/\n/g, '');
        let answerAndExplanation = nextSibling.innerHTML.split('<br>');
        let answer = answerAndExplanation.shift().replace(/\n/g, '');
        let explanation = answerAndExplanation.join('<br>').replace(/\n/g, '');
        results.push({
            statement: statement,
            imgHref: imgHref,
            options: options,
            answer: answer,
            explanation: explanation
        });
    }

    let nextDiv = pTags[i].nextElementSibling;
    if (nextDiv && nextDiv.tagName.toLowerCase() === 'div' && nextDiv.classList.contains('hk1_style-wrap5')) {
        let pre = nextDiv.getElementsByTagName('pre')[0];
        if (pre) {
            let nextP = nextDiv.nextElementSibling;
            if (nextP && nextP.tagName.toLowerCase() === 'p') {
                let nextDiv2 = nextP.nextElementSibling;
                if (nextDiv2 && nextDiv2.tagName.toLowerCase() === 'div' && nextDiv2.classList.contains('collapseomatic_content')) {
                    let statement = pTags[i].textContent;
                    let preContent = pre.textContent.replace(/\n/g, '');
                    let options = nextP.innerHTML.split('<br>').join('<br>').replace(/\n/g, '');
                    let answerAndExplanation = nextDiv2.innerHTML.split('<br>');
                    let answer = answerAndExplanation.shift().replace(/\n/g, '');
                    let explanation = answerAndExplanation.join('<br>').replace(/\n/g, '');
                    results.push({
                        statement: statement,
                        preContent: preContent,
                        options: options,
                        answer: answer,
                        explanation: explanation
                    });
                }
            }
        }

        let del1 = nextDiv.getElementsByClassName('del1')[0];
        if (del1) {
            let statement = pTags[i].textContent + ' ' + del1.textContent;
            let nextP = nextDiv.nextElementSibling;
            if (nextP && nextP.tagName.toLowerCase() === 'p') {
                let nextDiv2 = nextP.nextElementSibling;
                if (nextDiv2 && nextDiv2.tagName.toLowerCase() === 'div' && nextDiv2.classList.contains('collapseomatic_content')) {
                    let options = nextP.innerHTML.split('<br>').join('<br>').replace(/\n/g, '');
                    let answerAndExplanation = nextDiv2.innerHTML.split('<br>');
                    let answer = answerAndExplanation.shift().replace(/\n/g, '');
                    let explanation = answerAndExplanation.join('<br>').replace(/\n/g, '');
                    results.push({
                        statement: statement,
                        options: options,
                        answer: answer,
                        explanation: explanation
                    });
                }
            }
        }
    }
}

console.log(JSON.stringify(results, null, 2));


// ... Your existing code to extract the MCQs ...

// Now let's generate the HTML
let html = `
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"="width=device-width, initial-scale=1.0">
    <title>Quiz</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        @tailwind base;
        @tailwind components;
        @tailwind utilities;

        .option:hover:not(.selected) {
          @apply bg-gray-300;
        }
        .correct {
          @apply bg-green-200;
        }
        .incorrect {
          @apply bg-red-200;
        }
        .selected {
          @apply bg-gray-400;
        }
        .option:hover {
          @apply scale-105;
        }
        .selected {
          @apply scale-110;
        }
        .option:focus {
          @apply ring-4 ring-blue-500 ring-offset-2 ring-offset-gray-100;
        }
    </style>
</head>
<body class="bg-gray-100 p-10">

    <div class="flex justify-between items-center mb-4 sticky top-0 bg-white z-50">
        <div>
            <p class="text-lg font-bold">Time: <span id="timer" class="text-blue-500">00:00</span></p>
        </div>
        <div>
            <p class="text-lg font-bold text-green-500">Correct: <span id="correct-count">0</span></p>
            <p class="text-lg font-bold text-red-500">Incorrect: <span id="incorrect-count">0</span></p>
        </div>
    </div>



    ${results.map((result, index) => `
    <div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 flex flex-col my-2">
        <div class="md:flex mb-6">
            <div class="md:w-1/2 px-3">
                <label class="block uppercase tracking-wide text-blue-900 text-lg font-bold mb-2" for="grid-first-name">
                    Q${index + 1}: ${result.statement.replace(/^\d+\.\s*/, '')}
                </label>
                ${result.preContent ? `<pre>${result.preContent}</pre>` : ''}
            </div>
            <div class="md:w-1/2 px-3">
                ${result.imgHref ? `<img src="${result.imgHref}" alt="Image" class="mb-4">` : ''}
            </div>
        </div>
        <div class="md:flex mb-6">
            <div class="md:w-full px-3">
                <div id="options-${index}" class="grid grid-cols-1 md:grid-cols-2 gap-4">
                    ${result.options.split('<br>').map((option, optionIndex) => option.trim() !== "" ? `
                    <p class="option cursor-pointer py-2 px-4 rounded bg-blue-100 hover:bg-blue-200" onclick="checkAnswer(${index}, ${optionIndex})">${option}</p>
                    ` : '').join('')}
                </div>
                <button class="mt-3 text-white bg-blue-700 border-0 py-2 px-6 focus:outline-none hover:bg-blue-800 rounded text-lg" onclick="document.getElementById('answer-${index}').classList.toggle('hidden');document.getElementById('explanation-${index}').classList.toggle('hidden');">Show/Hide Answer</button>
                <p id="answer-${index}" class="hidden mt-3 text-grey-darker text-base bg-gray-200 p-4 rounded">${result.answer}</p>
                <p id="explanation-${index}" class="hidden mt-3 text-grey-darker text-base bg-gray-200 p-4 rounded">${result.explanation}</p>
            </div>
        </div>
    </div>
    `).join('')}
    <script src="script.js"></script>
</body>
</html>`;

// Download the file
let blob = new Blob([html], {type: "text/html;charset=utf-8"});
let link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "quiz.html";
link.click();});

    // Add an event listener to the button
    button.addEventListener('click', function() {
        // Execute the menu command
        GM_executeMenuCommand('Extract MCQs');
    });

})();