2017-10-21 58 views
3

Je suis en train de créer XML pour soumettre au service Mechanical Turks d'Amazon en utilisant la structure de données HTMLQuestion et la fonction create_hit de boto3. Selon la documentation, le format XML doit être formaté like this.Construction HTMLQuestion XML pour boto3 MTurk

J'ai créé une classe TurkTaskAssembler qui contient des méthodes pour générer le fichier XML et transmettre ce fichier XML à la plate-forme Mechanical Turks via l'API. J'utilise la bibliothèque boto3 pour gérer la communication avec Amazon.

Il semble que le XML que je suis génération est formaté de manière incorrecte, parce que quand je tente de transmettre cette XML via l'API, je reçois une erreur de validation, comme ceci:

>>> tta = TurkTaskAssembler("What color is the sky?") 
>>> response = tta.create_hit_task() 
>>> ParamValidationError: Parameter validation failed: Invalid type for parameter Question, value: <Element HTMLQuestion at 0x1135f68c0>, type: <type 'lxml.etree._Element'>, valid types: <type 'basestring'> 

je puis modifié la create_question_xml méthode pour convertir l'enveloppe XML à une chaîne en utilisant la méthode tostring, mais cela génère une autre erreur:

>>> tta = TurkTaskAssembler("What color is the sky?") 
>>> tta.create_hit_task() 
>>> ClientError: An error occurred (ParameterValidationError) when calling the CreateHIT operation: There was an error parsing the XML question or answer data in your request. Please make sure the data is well-formed and validates against the appropriate schema. Details: cvc-elt.1.a: Cannot find the declaration of element 'HTMLQuestion'. (1508611228659 s) 

Je ne suis pas sûr de ce que je fais mal et ont très peu d'expérience XML.

est ici tout le code correspondant:

import os 
import boto3 
from lxml.etree import Element, SubElement, CDATA, tostring 
from .settings import mturk_access_key_id, mturk_access_secret_key 

xml_schema_url = 'http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2011-11-11/HTMLQuestion.xsd' 


class TurkTaskAssembler(object): 

    def __init__(self, question): 
     self.client = boto3.client(
      service_name='mturk', 
      region_name='us-east-1', 
      endpoint_url='https://mturk-requester-sandbox.us-east-1.amazonaws.com', 
      aws_access_key_id=mturk_access_key_id, 
      aws_secret_access_key=mturk_access_secret_key 
     ) 
     self.question = question 

    def create_question_xml(self): 
     # questionFile = open(os.path.join(__location__, "question.xml"), "r") 
     # question = questionFile.read() 
     # return question 
     XHTML_NAMESPACE = xml_schema_url 
     XHTML = "{%s}" % XHTML_NAMESPACE 
     NSMAP = { 
      None : XHTML_NAMESPACE, 
      'xsi': 'http://www.w3.org/2001/XMLSchema-instance', 
      '' 
      } 
     envelope = Element("HTMLQuestion", nsmap=NSMAP) 

     html = """ 
      <!DOCTYPE html> 
      <html> 
      <head> 
       <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/> 
       <script type='text/javascript' src='https://s3.amazonaws.com/mturk-public/externalHIT_v1.js'></script> 
      </head> 
      <body> 
       <form name='mturk_form' method='post' id='mturk_form' action='https://www.mturk.com/mturk/externalSubmit'> 
       <input type='hidden' value='' name='assignmentId' id='assignmentId'/> 
       <h1>Answer this question</h1> 
       <p>{question}</p> 
       <p><textarea name='comment' cols='80' rows='3'></textarea></p> 
       <p><input type='submit' id='submitButton' value='Submit' /></p></form> 
       <script language='Javascript'>turkSetAssignmentID();</script> 
      </body> 
      </html> 
      """.format(question=self.question) 

     html_content = SubElement(envelope, 'HTMLContent') 
     html_content.text = CDATA(html) 
     xml_meta = """<?xml version="1.1" encoding="utf-8"?>""" 
     return xml_meta + tostring(envelope, encoding='utf-8') 

    def create_hit_task(self): 
     response = self.client.create_hit(
      MaxAssignments=1, 
      AutoApprovalDelayInSeconds=10800, 
      LifetimeInSeconds=10800, 
      AssignmentDurationInSeconds=300, 
      Reward='0.05', 
      Title='a title', 
      Keywords='some keywords', 
      Description='a description', 
      Question=self.create_question_xml(), 
     ) 
     return response 

Répondre

2

Pourquoi ne pas tout simplement les données XML dans un fichier XML séparé (comme vous l'avez fait, mais elle est commentée)? Cela vous éviterait d'avoir à intégrer plusieurs modules et beaucoup de code.

Utilisation du modèle que vous avez décrit here, créez question.xml:

<HTMLQuestion xmlns="http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2011-11-11/HTMLQuestion.xsd"> 
    <HTMLContent><![CDATA[ 
<!DOCTYPE html> 
<html> 
<head> 
    <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/> 
    <script type='text/javascript' src='https://s3.amazonaws.com/mturk-public/externalHIT_v1.js'></script> 
</head> 
<body> 
    <form name='mturk_form' method='post' id='mturk_form' action='https://www.mturk.com/mturk/externalSubmit'> 
    <input type='hidden' value='' name='assignmentId' id='assignmentId'/> 
    <h1>Answer this question</h1> 
    <p>{question}</p> 
    <p><textarea name='comment' cols='80' rows='3'></textarea></p> 
    <p><input type='submit' id='submitButton' value='Submit' /></p></form> 
    <script language='Javascript'>turkSetAssignmentID();</script> 
</body> 
</html> 
]]> 
    </HTMLContent> 
    <FrameHeight>450</FrameHeight> 
</HTMLQuestion> 

Ensuite, dans votre fonction create_question_xml():

def create_question_xml(self): 
    question_file = open("question.xml", "r").read() 
    xml = question_file.format(question=self.question) 
    return xml 

Cela devrait être tout ce que vous avez besoin.

+0

C'est une excellente suggestion, merci! Fonctionne parfaitement. –

0

Je pense que vous êtes un peu confus avec 3 formats Amazon vous suggère d'utiliser. De ce que je vois vous êtes allé avec HTMLQuestion. (Les deux autres sont: ExternalQuestion et QuestionFormData).

Pour conserver la question au format HTMLQuestion, utilisez simplement l'exemple simple fourni dans la documentation, inutile de l'envelopper au format XML. Voici une fonction fixe:

def create_question_html(self): 
    # you can extract template into a file, 
    # as @Mangohero1 suggested which would simplify code a bit. 

    return """ 
    <HTMLQuestion xmlns="http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2011-11-11/HTMLQuestion.xsd"> 
     <HTMLContent><![CDATA[ 
    <!DOCTYPE html> 
    <html> 
    <head> 
     <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/> 
     <script type='text/javascript' src='https://s3.amazonaws.com/mturk-public/externalHIT_v1.js'></script> 
    </head> 
    <body> 
     <form name='mturk_form' method='post' id='mturk_form' action='https://www.mturk.com/mturk/externalSubmit'> 
     <input type='hidden' value='' name='assignmentId' id='assignmentId'/> 
     <h1>{question}</h1> 
     <p><textarea name='comment' cols='80' rows='3'></textarea></p> 
     <p><input type='submit' id='submitButton' value='Submit' /></p></form> 
     <script language='Javascript'>turkSetAssignmentID();</script> 
    </body> 
    </html> 
    ]]> 
     </HTMLContent> 
     <FrameHeight>450</FrameHeight> 
    </HTMLQuestion> 
    """.format(question=self.question)