2011-05-07 4 views
0

J'interroge un service Web en utilisant urllib2.request et en recevant XML. Si je ne respecte pas la limite de débit du service Web (1 appel/seconde), je reçois un message HTML indiquant que j'ai enfreint la limite de débit.xml.dom.minidom.parse() échoue lorsque l'attribut XML contient unicode

Même si je peux time.sleep() pendant 2-3 secondes après chaque appel, je continue à enfreindre la limite de débit, quelle qu'en soit la raison.

Pour tester que ma réponse est XML ou HTML, j'utilise xml.dom.minidom() et ensuite tester la présence d'un élément html

try: 
    dom = xml.dom.minidom.parseString(response_text) 
    except xml.parsers.expat.ExpatError: 
    return False 

    if len(dom.getElementsByTagName('html')) == 0: 
    return True 
    else: 
    return False 

Cela fait le travail mais je J'ai rencontré un cas où l'un des attributs XML contient du XML. Dans ce cas, la commande échoue avec

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/opt/python/default-2.6/lib/python2.6/xml/dom/minidom.py", line 1918, in  parse 
    return expatbuilder.parse(file) 
    File "/opt/python/default-2.6/lib/python2.6/xml/dom/expatbuilder.py", line 924, in parse 
    result = builder.parseFile(fp) 
    File "/opt/python/default-2.6/lib/python2.6/xml/dom/expatbuilder.py", line 207, in parseFile 
    parser.Parse(buffer, 0) 
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 3125 

Dans ce cas, la colonne 3125 fait partie d'un texte de valeur d'attribut qui contient esperluette livres-x-9 (Stackoverflow se cache mon unicode) parseString().

Est-ce que xml.dom.minidom peut gérer cela? Pourrait-il y avoir un autre problème avec le XML à part cela qui provoque l'échec de l'analyse?

En outre, je suis ouvert à d'autres façons de gérer ce type de situation si la communauté en a un.

Si elle aide, voici ce que les retours de service Web quand je l'ai emporté violation de leur limite de vitesse:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="eng"> 
    <head> 
     <title>Service Temporarily Unavailable - Rate Limited</title> 
    </head> 
    <body style="text-align:center;background-color:white;"> 
     <h1>Service Temporarily Unavailable</h1> 
     <hr /> 
     <div> 
      You have used this service too often in a short time. Please wait before using this service again. 
      <br/><br/> 
      Please visit the <a href="http://wiki.xxxx.com/index.php?title=API_Usage">wiki</a> for more details. 
     </div> 
    </body> 
</html> 

Répondre

0

je pense que &#x9 est un onglet. Vous devriez essayer http://docs.python.org/library/htmllib.html#module-htmlentitydefs pour convertir des entités html spéciales à ce qu'elles sont. (Cela peut avoir le problème de &lt; etc). Ou vous pouvez faire une substitution de chaîne qui remplace &#x9 par un espace. À titre de suggestion, lorsque vous analysez des choses, et que l'analyseur rencontre un problème, comme ne pas ajuster votre motif, au lieu d'arrêter l'opération, vous devriez autoriser l'analyseur à continuer, mais cracher un avertissement . De cette façon, vous pouvez voir quel est le problème, et éventuellement le corriger, ou au moins voir qu'il y a un problème.

Toujours en ce qui concerne votre problème avec la limite de débit, pourquoi ne pas mettre en cache le code HTML demandé une fois pour pouvoir effectuer un traitement local.

+0

merci - je vais jeter un oeil. Le problème est que la limitation du débit de l'API du service Web tiers est rompue. Ils documentent 1 appel/seconde avec lequel je peux vivre mais même si je dors pendant 3+ secondes, je reçois toujours l'erreur occasionnelle de limite de taux. –

0

Vous pouvez également tester la chaîne pour HTML avant de tenter d'analyser le résultat:

if response_text.lstrip().startswith('<!DOCTYPE html'): 
    # we received an html response, sleep again 
... 

Je ne pouvais pas aussi minidom de faire sauter sur un attribut contenant une entité de tabulation. Peut-être est-ce une séquence d'entité mal terminée, comme &#9 sans le point-virgule de fin? Minidom semble correct avec les entités correctement échappées à l'intérieur des attributs:

text = '<root><a href="&#9;foo&lt;">link</a></root>' 
tree = minidom.parseString(text) 
print tree.toxml() 

u'<?xml version="1.0" ?>\n<root><a href="\tfoo&lt;">link</a></root>' 
Questions connexes