解析时转义错误 XML
Escaping bad XML while parsing
我正在尝试从不属于我的 XML 站点地图解析 URLs。不幸的是,有些 XML 写得不好,包含 unescaped/invalid 个字符,例如 & 符号。
这是我目前用来解析 XML 文件的代码块:
from xml.etree import ElementTree as ET
tree = ET.parse('test.xml')
root = tree.getroot()
name_space = '{http://www.sitemaps.org/schemas/sitemap/0.9}'
urls = []
for child in root.iter():
for block in child.findall('{}url'.format(name_space)):
for url in block.findall('{}loc'.format(name_space)):
urls.append('{}\n'.format(url.text))
with open('sample_urls.txt', 'w+') as f:
f.writelines(urls)
当遇到未转义的 URL 时,我 运行 陷入此错误:ParseError:格式不正确(无效令牌)。
如何避免这些问题并继续解析文件?我遇到了 escape() 模块的 xml.sax.saxutils 函数,但不确定应用它的最佳方法基于我目前拥有的。
如果可以,请尝试使用 lxml.html
。不过你应该小心;它会忽略名称空间,因此您需要确保 select 正在 select.
示例...
sitemap_products_1.xml(您链接到的那个的缩短版本。注意第二个 url
有一个错误的 loc
值。)
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
<url>
<loc>https://www.samsclub.com/sams/mirror-convex/prod13760282.ip</loc>
<image:image>
<image:title>See All 160 Degree Convex Security Mirror - 24" w x 15" h</image:title>
<image:loc>https://scene7.samsclub.com/is/image/samsclub/0003308171524_A</image:loc>
</image:image>
</url>
<url>
<loc>https://www.samsclub.com/sams/at&t-3-handset-cordless-phone/prod21064454.ip</loc>
<image:image>
<image:title>AT&T 3 Handset Cordless Phone</image:title>
<image:loc>https://scene7.samsclub.com/is/image/samsclub/0065053003067_A</image:loc>
</image:image>
</url>
<url>
<loc>https://www.samsclub.com/sams/premium-free-flow-waterbed-mattress-kit-queen/104864.ip</loc>
<image:image>
<image:title>Premium Free Flow Waterbed Mattress Kit- Queen</image:title>
<image:loc>https://scene7.samsclub.com/is/image/samsclub/0040649555859_A</image:loc>
</image:image>
</url>
</urlset>
Python 3.x
from lxml import html
tree = html.parse("sitemap_products_1.xml")
for elem in tree.findall(".//url/loc"):
print(elem.text)
Output(注意第二个 url 被完整打印出来。)
https://www.samsclub.com/sams/mirror-convex/prod13760282.ip
https://www.samsclub.com/sams/at&t-3-handset-cordless-phone/prod21064454.ip
https://www.samsclub.com/sams/premium-free-flow-waterbed-mattress-kit-queen/104864.ip
鉴于您发布的示例,我会说在 &
字符时使用正则表达式就足够了。也就是说,除非您完全想要删除此类 <loc/>
元素。下面的 "algorithm" 应该可以帮助您恢复此类错误。
由于.../at&t-3-handset-cordless...
里面的&t-
显然是
不是有效的符号字符代码,您可以捕获所有内容
在 &
和 <loc/>
值内的第一个 ;
之间,或者
结束标记的开始(</
,即 </loc>
)。
然后你可以检查捕获的字符串是否确实是一个
符号字符代码(因为这些是有限的,你可以创建一个
设置并检查字符串是否在里面)。如果不是,则更换
那个(只有那个!)与 &
字符串的符号。
从被替换的 &
所在的位置继续并继续迭代,直到您覆盖
完整的 <loc/>
元素。
之后你可以 运行 XML 解析器,因为所有无效的符号代码都被替换了,你应该能够得到一个格式正确的 XML,即除非还有其他问题。
请注意,这只是我的想法。
我正在尝试从不属于我的 XML 站点地图解析 URLs。不幸的是,有些 XML 写得不好,包含 unescaped/invalid 个字符,例如 & 符号。
这是我目前用来解析 XML 文件的代码块:
from xml.etree import ElementTree as ET
tree = ET.parse('test.xml')
root = tree.getroot()
name_space = '{http://www.sitemaps.org/schemas/sitemap/0.9}'
urls = []
for child in root.iter():
for block in child.findall('{}url'.format(name_space)):
for url in block.findall('{}loc'.format(name_space)):
urls.append('{}\n'.format(url.text))
with open('sample_urls.txt', 'w+') as f:
f.writelines(urls)
当遇到未转义的 URL 时,我 运行 陷入此错误:ParseError:格式不正确(无效令牌)。
如何避免这些问题并继续解析文件?我遇到了 escape() 模块的 xml.sax.saxutils 函数,但不确定应用它的最佳方法基于我目前拥有的。
如果可以,请尝试使用 lxml.html
。不过你应该小心;它会忽略名称空间,因此您需要确保 select 正在 select.
示例...
sitemap_products_1.xml(您链接到的那个的缩短版本。注意第二个 url
有一个错误的 loc
值。)
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
<url>
<loc>https://www.samsclub.com/sams/mirror-convex/prod13760282.ip</loc>
<image:image>
<image:title>See All 160 Degree Convex Security Mirror - 24" w x 15" h</image:title>
<image:loc>https://scene7.samsclub.com/is/image/samsclub/0003308171524_A</image:loc>
</image:image>
</url>
<url>
<loc>https://www.samsclub.com/sams/at&t-3-handset-cordless-phone/prod21064454.ip</loc>
<image:image>
<image:title>AT&T 3 Handset Cordless Phone</image:title>
<image:loc>https://scene7.samsclub.com/is/image/samsclub/0065053003067_A</image:loc>
</image:image>
</url>
<url>
<loc>https://www.samsclub.com/sams/premium-free-flow-waterbed-mattress-kit-queen/104864.ip</loc>
<image:image>
<image:title>Premium Free Flow Waterbed Mattress Kit- Queen</image:title>
<image:loc>https://scene7.samsclub.com/is/image/samsclub/0040649555859_A</image:loc>
</image:image>
</url>
</urlset>
Python 3.x
from lxml import html
tree = html.parse("sitemap_products_1.xml")
for elem in tree.findall(".//url/loc"):
print(elem.text)
Output(注意第二个 url 被完整打印出来。)
https://www.samsclub.com/sams/mirror-convex/prod13760282.ip
https://www.samsclub.com/sams/at&t-3-handset-cordless-phone/prod21064454.ip
https://www.samsclub.com/sams/premium-free-flow-waterbed-mattress-kit-queen/104864.ip
鉴于您发布的示例,我会说在 &
字符时使用正则表达式就足够了。也就是说,除非您完全想要删除此类 <loc/>
元素。下面的 "algorithm" 应该可以帮助您恢复此类错误。
由于
.../at&t-3-handset-cordless...
里面的&t-
显然是 不是有效的符号字符代码,您可以捕获所有内容 在&
和<loc/>
值内的第一个;
之间,或者 结束标记的开始(</
,即</loc>
)。然后你可以检查捕获的字符串是否确实是一个 符号字符代码(因为这些是有限的,你可以创建一个 设置并检查字符串是否在里面)。如果不是,则更换 那个(只有那个!)与
&
字符串的符号。从被替换的
&
所在的位置继续并继续迭代,直到您覆盖 完整的<loc/>
元素。
之后你可以 运行 XML 解析器,因为所有无效的符号代码都被替换了,你应该能够得到一个格式正确的 XML,即除非还有其他问题。
请注意,这只是我的想法。