站点地图 xml 在 python 3.x 中解析

sitemap xml parsing in python 3.x

我的xml结构如下

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
    <url>
        <loc>hello world 1</loc>
        <image:image>
            <image:loc>this is image loc 1</image:loc>
            <image:title>this is image title 1</image:title>
        </image:image>
        <lastmod>2019-06-19</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.25</priority>
    </url>
    <url>
        <loc>hello world 2</loc>
        <image:image>
            <image:loc>this is image loc 2</image:loc>
            <image:title>this is image title 2</image:title>
        </image:image>
        <lastmod>2020-03-19</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.25</priority>
    </url>
</urlset>

我只想得到

hello world 1
hello world 2

我的 python 代码如下:

import xml.etree.ElementTree as ET
tree = ET.parse('test.xml')
root = tree.getroot()

for url in root.findall('url'):
    loc = url.find('loc').text
    print(loc)

不幸的是,它什么也没给我。

但是当我将 xml 更改为

<urlset>
    <url>
        <loc>hello world 1</loc>
        <lastmod>2019-06-19</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.25</priority>
    </url>
    <url>
        <loc>hello world 2</loc>
        <lastmod>2020-03-19</lastmod>
        <changefreq>daily</changefreq>
        <priority>0.25</priority>
    </url>
</urlset>

它给了我正确的结果。

hello world 1
hello world 2

如何在不更改 xml 的情况下获得正确的结果?因为修改10000+行文件没有任何意义。

TIA

对您的代码的(不雅)修复是:

import xml.etree.ElementTree as ET
tree = ET.parse('test.xml')
root = tree.getroot()

# In find/findall, prefix namespaced tags with the full namespace in braces
for url in root.findall('{http://www.sitemaps.org/schemas/sitemap/0.9}url'):
    loc = url.find('{http://www.sitemaps.org/schemas/sitemap/0.9}loc').text
    print(loc)

这是因为您必须使用定义 XML 的命名空间来限定标签名称。有关如何将 findfindall 方法与命名空间一起使用的详细信息来自

如果你不想弄乱命名空间,这是比公认答案更简单的解决方案,而且更优雅,使用通用 xpath 查询:

import lxml.etree


tree = lxml.etree.parse('test.xml')

for url in tree.xpath("//*[local-name()='loc']/text()"):
    print(url)

如果您更喜欢使用 xml 命名空间,您应该这样做:

import lxml.etree


tree = lxml.etree.parse('test.xml')

namespaces = {
    'sitemapindex': 'http://www.sitemaps.org/schemas/sitemap/0.9',
}

for url in tree.xpath("//sitemapindex:loc/text()", namespaces=namespaces):
    print(url)

如果您更喜欢直接从内存而不是文件加载 xml 数据,您可以使用 lxml.etree.fromstring 而不是 lxml.etree.parse。