【问题标题】:Error when using XML API findall() in with python 2.6在 python 2.6 中使用 XML API findall() 时出错
【发布时间】:2014-12-01 11:17:35
【问题描述】:

我正在使用下面的这段代码从 Alexa API 检索信息,这段代码在 Python 2.7 上运行良好,但我必须使用 Python 2.6,它给了我一个错误:findall() 只需要 2 个参数( 3 个)

我认为这个方法在 Python 2.7 中有所改变,但我不知道如何让它在 2.6 中工作。

NS_PREFIXES = {
    "alexa": "http://alexa.amazonaws.com/doc/2005-10-05/",
    "awis": "http://awis.amazonaws.com/doc/2005-07-11",
}

tree = api.sites_linking_in(domain + ".eu", count=10, start=0)
alexa_sites_linkin_in = {}
for element in tree.findall('//awis:SitesLinkingIn/awis:Site',NS_PREFIXES):
    alexa_sites_linkin_in.update({
    element.find('awis:Title', NS_PREFIXES).text: element.find('awis:Url', "awis").text})

感谢您的帮助。

【问题讨论】:

  • 你在使用this documentation中的xml.etree.ElementTree的findall函数吗?我不确定这在 Python 2.7 中是如何工作的,只要文档只提到 1 个参数(不包括自我)。
  • 它尝试导入 xml.etree.cElementTree,如果失败则导入 xml.etree.ElementTree。

标签: python xml api alexa


【解决方案1】:

该 api 使用lxml(ElementTree 作为 backport) 来解析 xml。 lxml allowed 附加参数 - 命名空间,但 ElementTree 不允许。那是问题。 所以作为修补程序,我建议安装 lxml。

【讨论】:

    【解决方案2】:

    对于 Python 2.6(及更早版本),您需要手动注册命名空间并将其解析为 Clark 表示法,以便 find() 能够识别它们。

    首先,按照http://effbot.org/zone/element-namespaces.htm中的描述注册命名空间:

    from xml import ElementTree
    try:
        register_namespace = ElementTree.register_namespace
    except AttributeError:
        def register_namespace(prefix, uri):
            ElementTree._namespace_map[uri] = prefix
    
    for short_name, url in NS_PREFIXES.items():
        register_namespace(short_name, url)
    

    接下来,您需要自己将命名空间 XPath 解析为 Clark 表示法,find() 在内部使用该表示法。例如,awis:Title 解析为 {http://awis.amazonaws.com/doc/2005-07-11}Title

    def resolved_xpath(xpath, namespace):
        result = xpath
        for short_name, url in namespace.items():
            result = re.sub(r'\b' + short_name + ':', '{' + url + '}', result)
        return result
    

    现在很容易编写修改后的 find()findall(),即使在 Python 2.6 中也能尊重命名空间:

    def find_with_namespace(element, xpath, namespace):
        return element.find(resolved_xpath(xpath, namespace))
    
    def findall_with_namespace(element, xpath, namespace):
        return element.findall(resolved_xpath(xpath, namespace))
    

    您的示例可以实现为:

    NS_PREFIXES = {
        "alexa": "http://alexa.amazonaws.com/doc/2005-10-05/",
        "awis": "http://awis.amazonaws.com/doc/2005-07-11",
    }
    
    tree = api.sites_linking_in(domain + ".eu", count=10, start=0)
    alexa_sites_linkin_in = {}
    for element in findall_with_namespace(tree, '//awis:SitesLinkingIn/awis:Site',NS_PREFIXES):
        title = find_with_namespace(element, 'awis:Title', NS_PREFIXES).text
        url = find_with_namespace(element, 'awis:Url', NS_PREFIXES).text
        alexa_sites_linkin_in[title] = url
    

    所以,是的,如果可能,请使用lxml

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-19
      • 1970-01-01
      相关资源
      最近更新 更多