我正在使用urllib2.request查询Web服务并接收XML。如果我违反了网络服务的速率限制(1个通话/秒),我会收到HTML,说我违反了速率限制。
即使我在每次通话后都能在time.sleep()上停留2-3秒,但无论出于何种原因,我仍然违反了速率限制。
要测试我的响应是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是包含ampersand-pound-x-9的某些属性值文本的一部分(Stackoverflow隐藏了我的unicode)。
xml.dom.minidom应该能够处理吗?除此之外,还有另一个问题是导致解析失败吗?
此外,如果社区有这种情况,我会采取其他方式来处理这种情况。
如果有帮助,那么当我违反其速率限制时,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 :(得分:0)
我认为	
是一个标签。您应该尝试http://docs.python.org/library/htmllib.html#module-htmlentitydefs将特殊的html实体转换回它们的任何内容。 (这可能有<
等问题。或者您可以使用空格替换	
的字符串替换。
正如一个建议,当你解析东西,并且解析器遇到问题时,例如不适合你的模式,而不是停止操作,你应该允许解析器继续,但吐出警告。通过这种方式,您可以看到问题所在,并可能对其进行纠正,或至少发现存在问题。
另外,关于速率限制的问题,为什么不缓存请求的HTML一次,以便您可以在本地执行处理。
答案 1 :(得分:0)
在尝试解析结果之前,您还可以测试HTML的字符串:
if response_text.lstrip().startswith('<!DOCTYPE html'):
# we received an html response, sleep again
...
我也无法让minidom炸毁包含制表符实体的属性。也许它是一个不正确终止的实体序列,如	
没有结尾的分号? Minidom似乎可以使用属性中正确转义的实体:
text = '<root><a href="	foo<">link</a></root>'
tree = minidom.parseString(text)
print tree.toxml()
u'<?xml version="1.0" ?>\n<root><a href="\tfoo<">link</a></root>'