2011-05-07 170 views
0

我使用urllib2.request查询Web服务并接收XML。如果我违反了网络服务的速率限制(1次/秒),我会收到HTML说我违反了费率限制。xml.dom.minidom.parse()在XML属性包含unicode时失败

即使我可以在每次通话后2-3秒钟使用time.sleep(),但我仍然无论出于何种原因都违反了费率限制。

为了测试我的反应是XML或HTML,我使用xml.dom.minidom(),然后测试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 

这干得不错,但我已经遇到了其中一个XML属性包含XML的情况。在这种情况下,parseString()命令失败,

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 

在这种情况下,列3125是包含符号磅-X-9一些属性值的文本的一部分(#1被隐藏我的unicode)。

xml.dom.minidom应该能够处理这个问题吗?除此之外,XML可能还存在另一个问题,导致解析失败?

另外,如果社区有一个,我愿意接受其他处理这种情况的方法。

如果有帮助,这里是什么,当我已经侵犯了他们的速率限制Web服务回报:

<!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> 

回答

0

我认为&#x9是一个标签。您应该尝试http://docs.python.org/library/htmllib.html#module-htmlentitydefs将特殊的html实体转换回它们的任何内容。 (这可能有&lt;等问题)。或者你可以做一个字符串替换,用空格替换&#x9

正如一个建议,当你解析东西时,解析器遇到问题,比如不适合你的模式,而不是停止操作,你应该允许解析器继续,但吐出一个警告。通过这种方式,您可以查看问题所在,并且可能会纠正问题,或者至少可以看到问题所在。

同样对于您的速率限制问题,为什么不缓存所请求的HTML一次,以便您可以在本地执行处理。

+0

谢谢 - 我来看看。问题在于第三方Web服务的API速率限制被打破。他们记录了我可以接受的每秒1次通话,但即使我睡了3秒以上,我仍然会收到偶尔的速率限制错误。 – 2011-05-07 16:25:36

0

你也可以尝试分析结果之前测试HTML字符串:

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

我也无法得到minidom命名炸毁含标签实体的属性。也许这是一个不正确的终止实体序列,如&#9没有结尾分号? Minidom似乎没有妥善逃脱的实体属性内:

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>'