[Script] MLDatalabeler script help

Discussion in 'mTurk Scripts & Resources' started by hyperkilljoy, Sep 4, 2019.

  1. hyperkilljoy

    hyperkilljoy New Turker

    Messages:
    14
    Gender:
    Male
    Ratings:
    +5
    Code:
    // ==UserScript==
    // [USER=7839]@Name[/USER]         Classify text
    // @namespace    http://tampermonkey.net/
    // @version      0.1
    // @description  try to take over the world!
    // @author       You
    // [USER=6575]@Grant[/USER]        GM_log
    // @include      /^http(s)?://worker\.mturk\.com/
    // @require      https://code.jquery.com/jquery-3.4.1.min.js
    // ==/UserScript==
    (function() {
    var Sanity = "Classify the text you see ";
    var SanityTwo = "Classify the image you see ";
        if ($("annotation-area header").text() === Sanity){
         console.log("Classify text Running");
        }
        else if ($("annotation-area header").text() === SanityTwo){
            console.log("Sanity Two Classify text running");
        }
        else {
         console.log("Classify text Not running");
        }
    })();
    
    
    I've got that already, but the last else is always the one being hit. Any ideas?
     
    Last edited: Sep 8, 2019
  2. Ornac

    Ornac Survey Slinger

    Messages:
    6,011
    Gender:
    Male
    Ratings:
    +5,553
    It's not liking this part of the statements:

    I've been mucking with it for a bit and can't get it to return anything using a console.log with a variety of things in the quotes that I think should maybe work.

    I know that's not really helpful, I was just interested in the answer as well so figured I'd bump this and hope someone who knows what they're doing happens by.
     
  3. Fuzzy_Dunlop

    Fuzzy_Dunlop Turker

    Messages:
    95
    Gender:
    Male
    Ratings:
    +22
    I have never used JQuery, so these corrections are in theory only.

    I got a bit carried away with the comments, but the issue was a simple fix (syntax) . With the shorthand selector, $(), a selection query such as $("annotation-area header") needs to identify whether these items are an ID, class, element, attribute.....

    Code:
    
    /*
     * Sample HTML Element (for reference)
     *	`<p class="annotation-area header style-scope crowd-bounding-box">` +
     *	`Only label these exact chairs you see on the left. Do not label other chairs/sofas.` +
     *	`</p>`;
     *
     *
     * Working Options
     * $("p.annotation-area.header").text();
     * $(".annotation-area.header").text();
     *
     *
     *
     * $("element")
     *    $("p") : <p>Some Test</p>
     *    $("h2") : <h2>Some Other Text</h2>
     * $(".class") OR $(".class1.class2")
     *     $(".annotation-area.header") : class="annotation-area header"
     * $("#id")
     *    $("p#test_value.test_class") : <p id="test_value" class="test_class">
     */
    
    Two periods did the trick:
    annotation-area >>>> .annotation-area
    header >>>> .header

    Code:
    // ==UserScript==
    // @name Classify text
    // @version 0.1
    // @description try to take over the world!
    // @grant GM_log
    // @match *://worker.mturk.com*
    // @match *://bxcb.public-workforce.us*
    // @require https://code.jquery.com/jquery-3.4.1.min.js
    // ==/UserScript==
    
    
    
    /*
     * Switches focus from the Amazon page to the public-workforce.us iframe *
     * With this, you can generally have the page ready to accept the keyboard
     * input for selecting a category.
    */
    if (document.querySelector("iframe")) document.querySelector("iframe");
    
    
    
    /*
     * The annotation areas for MLD hits takes an unreasonable
     * amount of time to load compared to the parent Amazon page.
     *
     * Because of this, if you try to check for the sanity value before
     * all of that extra garbage loads, the text inside the <p> element
     * may not have loaded yet.
     *
     * I have found 1 to 2 seconds is the sweet spot, but you may need to tweak it
     */
    window.onload=setTimeout(function() {
            /*
    	 * Is the space at the end neccessary?
    	 * A === will return will not ignore extra whitespace, however
    	 * something like if(elementText.includes(sanity_text))
    	 * can search a larger piece of text for a piece of a sentence
    	 */
            var Sanity = "Classify the text you see ";
            var SanityTwo = "Classify the image you see ";
    
            /*
    	 * You may want to consider using const instead of var for the Sanity variables
    	 * Additionally, if you have multiple values,
    	 * you may find it more simple to use an array of sanity check strings.
    	 *
    	 * const SANITY=["Classify the text you see ","Classify the image you see "];
    	 * SANITY[0] || SANITY[1]
    	 */
    
            if ( $(".annotation-area.header").text() === Sanity )
    		console.log("Classify text Running");
            else if ( $(".annotation-area.header").text() === SanityTwo )
    		console.log("Sanity Two Classify text running");
            else
    		console.log("Classify text Not running");
            
    }, 2000);
    
    
    
     
    • Like Like x 1
    • Useful / Informative Useful / Informative x 1
    Last edited: Sep 4, 2019
  4. Ornac

    Ornac Survey Slinger

    Messages:
    6,011
    Gender:
    Male
    Ratings:
    +5,553
    No more is definitely better. I tried this

    and still wasn't getting anything, so I would have still been confused if you hadn't included:

    I have a decent background in programming, but no experience with web stuff past really simple scripts for hits. I thought I would try to help @hyperkilljoy out as a way to learn a bit, but got stumped. Thanks a lot for the solution!
     
  5. Fuzzy_Dunlop

    Fuzzy_Dunlop Turker

    Messages:
    95
    Gender:
    Male
    Ratings:
    +22
    Guessing you're on a chrome based browser then?
    Chromium does not make it as convenient to cut through the element hierarchy like with Firefox. No idea why yet, or if there is an easier workaround.

    The two examples below are how I work around the issue on the rare occasion I'm not on Firefox. I usually just walk it down one <div> at a time and keep a look out for the #shadow-root elements.


    Code:
    /* Find submit button & click */
    document.querySelector("crowd-bounding-box")
            .shadowRoot.querySelector("div[id=react-mount-point]")
            .querySelector("div[class=awsui]")
            .querySelector("footer[id=footerContainer]")
            .querySelector("div[id=actionsContainer]")
            .querySelector("button")
            .click();
    


    Code:
    /*
     *  Locates the paragraph element ('p') that holds the title at the top of 
     *  one of the furniture image classification tasks. (ONLY label this type of chair)
     *
     *  returns: Only label these exact chairs you see on the left. Do not label other chairs/sofas.
     */
    document .querySelector("crowd-bounding-box")
            .shadowRoot.querySelector("div#react-mount-point")
            .querySelector("div.awsui")
            .querySelector("div.annotation-area")
            .querySelector("p").innerText;
    
     
    • Useful / Informative Useful / Informative x 1
  6. Ornac

    Ornac Survey Slinger

    Messages:
    6,011
    Gender:
    Male
    Ratings:
    +5,553
    No Firefox, but when I said I had tried "p.annotation-area.header" it was before you posted on the thread, when I was looking at it the first time. This works fine for me:

    But a lot of people use Chrome and I'm sure they'll find this helpful.

    Thanks again, like I said I was mostly playing with this to learn and you helped a lot with that.
     
  7. hyperkilljoy

    hyperkilljoy New Turker

    Messages:
    14
    Gender:
    Male
    Ratings:
    +5
    Code:
    (function() {
        'use strict';
        // Your code here...
        /*
     * Switches focus from the Amazon page to the public-workforce.us iframe *
     * With this, you can generally have the page ready to accept the keyboard
     * input for selecting a category.
    */
    if (document.querySelector("iframe")) document.querySelector("iframe");
    /*
     * The annotation areas for MLD hits takes an unreasonable
     * amount of time to load compared to the parent Amazon page.
     *
     * Because of this, if you try to check for the sanity value before
     * all of that extra garbage loads, the text inside the <p> element
     * may not have loaded yet.
     *
     * I have found 1 to 2 seconds is the sweet spot, but you may need to tweak it
     */
    window.onload=setTimeout(function() {
            /*
        * Is the space at the end neccessary?
        * A === will return will not ignore extra whitespace, however
        * something like if(elementText.includes(sanity_text))
        * can search a larger piece of text for a piece of a sentence
        */
            var Sanity = "Classify the text you see ";
            var SanityTwo = "How would you rate the following answers in relation to the provided question?";
            /*
        * You may want to consider using const instead of var for the Sanity variables
        * Additionally, if you have multiple values,
        * you may find it more simple to use an array of sanity check strings.
        *
        * const SANITY=["Classify the text you see ","Classify the image you see "];
        * SANITY[0] || SANITY[1]
        */
            if ( $(".annotation-area.header").text() === Sanity )
            console.log("Classify text Running");
            else if ( $(".annotation-area.header").text() === SanityTwo )
            console.log("Sanity Two Classify text running");
            else
            console.log("Classify text Not running");
    }, 2000);
    })();
    
    I copy-pasted that which didn't work.

    I got this to work on W3schools but not on the mturk page itself. (Took out the button for mturk)
    Code:
    <!DOCTYPE html>
    <html>
    <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script>
    $(document).ready(function() {
        'use strict';
        // Your code here...
        const Sanity      = ['How would you rate the following answers in relation to the provided question?','Classify the text you see','Classify the image you see'];
    
            if ($("p.annotation-area").text() === Sanity[0]) {
                console.log('true', Sanity[0])
                  $("button").click(function(){
                    $("p.annotation-area").toggle();
                })
    
            }
            else if ($("p.annotation-area").text() === Sanity[1]) {
                console.log('true', Sanity[1])
                  $("button").click(function(){
                    $("p.annotation-area").toggle();
                })
            }
            else if ($("p.annotation-area").text() === Sanity[2]) {
                console.log('true', Sanity[2])
                  $("button").click(function(){
                    $("p.annotation-area").toggle();
                })
            }
            else {
                console.log('false');
            }
    
    });
    </script>
    </head>
    <body>
    
    <h2>This is a heading</h2>
    
    <p>This is a paragraph.</p>
    <p>This is another paragraph.</p>
    
    <p class="annotation-area header">Classify the image you see</p>
    
    <button>Click me to hide paragraphs</button>
    
    </body>
    </html>
    Do I have to navigate all of the divs that it is contained in first?
    Code:
    /*
     *  Locates the paragraph element ('p') that holds the title at the top of
     *  one of the furniture image classification tasks. (ONLY label this type of chair)
     *
     *  returns: Only label these exact chairs you see on the left. Do not label other chairs/sofas.
     */
    document .querySelector("crowd-bounding-box")
            .shadowRoot.querySelector("div#react-mount-point")
            .querySelector("div.awsui")
            .querySelector("div.annotation-area")
            .querySelector("p").innerText;
    gives me an error of:
    Cannot read property 'shadowRoot' of null

    This is all google chrome
     
    Last edited: Sep 7, 2019
  8. Fuzzy_Dunlop

    Fuzzy_Dunlop Turker

    Messages:
    95
    Gender:
    Male
    Ratings:
    +22
    the page layout is going to be a little different depending on the browser, version, extensions/addons & any other scripts. The example was just to give you an idea how process works. I can't speak on jquery, and there very well may be a more efficient method, but here is how I troubleshoot a value in the browser's console so that I can find the element I am looking for.
    Code:
    let level1=document.querySelector("crowd-bounding-box");
    let level2=level1.shadowRoot.querySelector("div#react-mount-point");
    let level3=level2.querySelector("div.awsui");
    let level4=level3.querySelector("div.annotation-area");
    let level5=level4.querySelector("p").innerText;
    
    [​IMG]
     
  9. hyperkilljoy

    hyperkilljoy New Turker

    Messages:
    14
    Gender:
    Male
    Ratings:
    +5
    upload_2019-9-8_3-32-12.png

    Your code looks perfect.
    It's just the shadow root part it gets stuck on. It all looks fine but this shadowroot thing is giving me problems. Every example I've looked at says that it should work. I'm new to WebDev and never seen shadowroot before though.
    Here is the page I've been using.

    https://bxcb.public-workforce.us-east-1.sagemaker.aws/work?ui=33c5d5899d4570936edae163689cfaf86f0fcff5&assignmentId=3JWH6J9I9U1EHOWG9NP5MOECRYRNB5&hitId=3I6NF2WGIHK4VW0RV7GV4Z9YKZFG5O&workerId=AQ6CGN5UQ1LBB&turkSubmitTo=https://www.mturk.com

    const armageddon = $("crowd-classifier").shadowRoot;
    const mturkHit = armageddon.querySelector("#react-mount-point").querySelector(".awsui").querySelector(".annotation-area").querySelector("p").innerText;
    console.log(mturkHit);

    I got that to work, but it gives me querySelector null. Copy paste that into the ppage when it loads, I get the result and then I get undefined underneath
     

    Attached Files:

    Last edited: Sep 8, 2019
  10. hyperkilljoy

    hyperkilljoy New Turker

    Messages:
    14
    Gender:
    Male
    Ratings:
    +5
    Got it working. Thanks a lot for everyone's help!

    That shadowRoot was a roadblock for awhile.

    It's just basic atm. But here it is :)

    Code:
    // ==UserScript==
    // @name         MLDataLabeler
    // @namespace    http://tampermonkey.net/
    // @author       Hyperkilljoy (credits to Fuzzy_Dunlop & Ornac of www.turkerview.com for the help)
    // @version      0.1
    // @description  try to take over the world!
    // @grant        GM_log
    // @include      /^http(s)?://worker\.mturk\.com/
    // @include      https://bxcb.public-workforce.us*
    // ==/UserScript==
    window.onload=setTimeout(function() {
    
    const form1 = document.querySelector("body > crowd-form > form > crowd-classifier").shadowRoot;
    const form2 = form1.querySelector("div#react-mount-point > div.awsui > div > div > awsui-app-layout.awsui-util-no-gutters");
    const form3 = form2.querySelector("div.awsui-app-layout > main.awsui-app-layout__content > div.awsui-app-layout__content--scrollable");
    const form4 = form3.querySelector("div > span > span > div.annotation-area.container");
    const form5 = form4.querySelector("p.annotation-area.header").innerText;
    
    const Sanity = ['How would you rate the following answers in relation to the provided question?','Classify the text you see','Classify the image you see'];
    
             if (form5 === Sanity[0]) {
                 //Do Stuff
                 console.log('Answer Validation:   ', Sanity[0]);
             }
             else if (form5 === Sanity[1]) {
                 //Do Stuff
                 console.log('Classify Text:   ', Sanity[1]);
             }
             else if (form5 === Sanity[2]) {
                 //Do Stuff
                 console.log('Classify Image:   ', Sanity[2]);
             }
             else {
                 //Do Stuff
                 console.log('Not one of the three MLDataLabelers included.');
             }
    }, 2000);
     
    • Like Like x 1
    Last edited: Sep 8, 2019
  11. Fuzzy_Dunlop

    Fuzzy_Dunlop Turker

    Messages:
    95
    Gender:
    Male
    Ratings:
    +22
    Code:
    // ==UserScript==
    // @name         MLDataLabeler
    // @namespace    http://tampermonkey.net/
    // @author       Hyperkilljoy (credits to Fuzzy_Dunlop & Ornac of www.turkerview.com for the help)
    // @version      0.1
    // @description  try to take over the world!
    // @grant        GM_log
    // @include      /^http(s)?://worker\.mturk\.com/
    // @include      https://bxcb.public-workforce.us*
    // ==/UserScript==
    
    window.onload = setTimeout(function() {
    	let check = document
    		.querySelector("body > crowd-form > form > crowd-classifier")
    		.shadowRoot.querySelector(
    			`#react-mount-point > div > div > div > awsui-app-layout > div > main >
    			div.awsui-app-layout__content--scrollable > div > span > span > div > p`
    		).innerText;
    
    	const Sanity = [
    		"How would you rate the following answers in relation to the provided question?",
    		"Classify the text you see",
    		"Classify the image you see"
    	];
    
    	if (check === Sanity[0]) {
    		//Do Stuff
    		console.log(`Answer Validation:\t`, Sanity[0]);
    	} else if (check === Sanity[1]) {
    		//Do Stuff
    		console.log(`Classify Text:\t`, Sanity[1]);
    	} else if (check === Sanity[2]) {
    		//Do Stuff
    		console.log(`Classify Image:\t`, Sanity[2]);
    	} else {
    		//Do Stuff
    		console.log("Not one of the three MLDataLabelers included.");
    	}
    }, 2000);
    
    
    The level1/level2/level3... was more of an example on how to break it down for troubleshooting. I cleaned it up one step further for you. Also, instead of the extra space, you can do a \t which will insert a tab character (4 or 8 spaces depending on your browser settings).
     
  12. hyperkilljoy

    hyperkilljoy New Turker

    Messages:
    14
    Gender:
    Male
    Ratings:
    +5
    Couple dumb questions incoming...
    1.) Figured it out.... I'm dumb.

    2.) I'm trying to add https://bxcb.public-workforce.us-east-1.sagemaker.aws/work?ui=a50d266707814e013e9dbca473e9abfd1ee13fdb&assignmentId=3P59JYT76N8IR339UB1IM3OE8D62TJ&hitId=3VLL1PIENRCQX23KXZJWRKWEOZXOZU&turkSubmitTo=https://www.mturk.com to it, but after the (form > crowd-classifier") it's (form > crowd-image-classifier")

    I googled for hours looking up shadowRoot and learning it, but today, it works; yesterday it didn't...
     
    Last edited: Sep 15, 2019 at 6:07 PM
  13. hyperkilljoy

    hyperkilljoy New Turker

    Messages:
    14
    Gender:
    Male
    Ratings:
    +5
    Thought I would do some tidying up since the last post I made.

    Code:
    // ==UserScript==
    // @name         MLDataLabeler
    // @namespace    http://tampermonkey.net/
    // @author       Hyperkilljoy (credits to Fuzzy_Dunlop & Ornac of www.turkerview.com for the help)
    // @version      0.4
    // @description  Basic starting blocks for 3 of the MDataLabeler Mturk tasks (Answer Validation, Classify Text & Classify Image)
    // @grant        GM_log
    // @include      /^http(s)?://worker\.mturk\.com/
    // @include      https://bxcb.public-workforce*
    // ==/UserScript==
    if (document.querySelector("iframe")) document.querySelector("iframe");
    
    window.onload=setTimeout(function() {
    
        const Sanity = ['How would you rate the following answers in relation to the provided question?','Classify the text you see','Classify the image you see'];
    
        try {
            const answer = document.querySelector("body > crowd-form > form > crowd-classifier")
                  .shadowRoot.querySelector(`div > div > div > div > awsui-app-layout.awsui-util-no-gutters >
                                            div > main > div > div > span > span > div > p`).innerText;
            if (answer === Sanity[0]) {
                //Do Stuff
                console.log('Answer Validation:\t', Sanity[0]);
            }
        }
        catch (e) {
            // Catch the errors here
        }
        try {
            const text = document.querySelector("body > crowd-form > form > crowd-classifier")
            .shadowRoot.querySelector(`div > div > div > div > awsui-app-layout.awsui-util-no-gutters.awsui-app-layout--mobile >
                                      div > main > div.awsui-app-layout__content--scrollable > div > span > span > div > p`).innerText;
            if (text === Sanity[1]) {
                //Do Stuff
                console.log('Classify Text:\t', Sanity[1]);
            }
        }
        catch(e) {
            // Catch the errors here
        }
        try {
            const image = document.querySelector("body > crowd-form > form > crowd-image-classifier")
            .shadowRoot.querySelector(`div > div > div > div > awsui-app-layout.awsui-util-no-gutters.awsui-app-layout--mobile >
                                      div > main > div.awsui-app-layout__content--scrollable > div > span > span > div > p`).innerText;
            if (image === Sanity[2]) {
                //Do Stuff
                console.log('Classify Image:\t', Sanity[2]);
            }
        } catch(e) {
            // Catch the errors here
        }
        // waits 3 second for the window to load
    }, 3000);
    Any critiques are greatly appreciated. My first script :)
     
    • Like Like x 2
    Last edited: Sep 15, 2019 at 6:08 PM
  14. Nikoratos

    Nikoratos Turker

    Messages:
    76
    Gender:
    Male
    Ratings:
    +66
    Which end is the pointy end? I'm at the level of touching bare wires together and hoping for something good to happen in regards to userscripts. And for nothing to explode.
     
  15. DarkChild

    DarkChild Survey Slinger

    Messages:
    6,666
    Gender:
    Male
    Ratings:
    +11,102
    hey man, might wanna edit this frame link as it contains your worker ID.
     
    Last edited: Sep 15, 2019 at 10:11 PM
  16. hyperkilljoy

    hyperkilljoy New Turker

    Messages:
    14
    Gender:
    Male
    Ratings:
    +5
    Ok. Is that a bad thing?
     
  17. DarkChild

    DarkChild Survey Slinger

    Messages:
    6,666
    Gender:
    Male
    Ratings:
    +11,102
    You don't want other people to have it generally. It's your unique ID as a worker, which is submitted alongside all the work you do. It's generally something we've decided shouldn't be shared for the safety of your account.
     
    • Like Like x 2
  18. Nikoratos

    Nikoratos Turker

    Messages:
    76
    Gender:
    Male
    Ratings:
    +66
    Good looking out :emoji_thumbsup:
     
  19. Mark Staas

    Mark Staas New Turker

    Messages:
    7
    Gender:
    Male
    Ratings:
    +0
    Soooo what's it do?
     
  20. hyperkilljoy

    hyperkilljoy New Turker

    Messages:
    14
    Gender:
    Male
    Ratings:
    +5
    It's just the building blocks of an MLDataLabeler script I was working on. So far it just checks if you're doing one of the three jobs I put in; nothing else. If you've watched the learning to script videos on here, it's just the Sanity checks.