python - 在 python 中使用 lxml iterparse 解析大型 .bz2 文件 (40 GB)。未压缩文件不会出现的错误

标签 python xml lxml openstreetmap

我正在尝试解析以 bz2 格式压缩的 OpenStreetMap 的 planet.osm。因为已经41G了,不想解压完全。

所以我想出了如何使用 bz2 和 lxml 解析 planet.osm 文件的部分,使用以下代码

from lxml import etree as et
from bz2 import BZ2File

path = "where/my/fileis.osm.bz2"
with BZ2File(path) as xml_file:
    parser = et.iterparse(xml_file, events=('end',))
    for events, elem in parser:

        if elem.tag == "tag":
            continue
        if elem.tag == "node":
            (do something)


    ## Do some cleaning
    # Get rid of that element
    elem.clear()

    # Also eliminate now-empty references from the root node to node        
    while elem.getprevious() is not None:
        del elem.getparent()[0]

Geofabrick extracts 完美配合.但是,当我尝试使用相同的脚本解析 planet-latest.osm.bz2 时,出现错误:

xml.etree.XMLSyntaxError: Specification mandate value for attribute num_change, line 3684, column 60

这是我尝试过的:

  • 检查planet-latest.osm.bz2 md5sum
  • 检查带有 bz2 的脚本停止的 planet-latest.osm。没有明显的错误,该属性称为“num_changes”,而不是错误中指示的“num_change”
  • 我还做了一些愚蠢的事情,但这个错误让我很困惑:我以 'rb' [c = BZ2File('file.osm.bz2', 'rb')] 模式打开了 planet-latest.osm.bz2,然后将 c.read() 传递给 iterparse(),它向我返回了一条错误消息,提示无法打开(非常长的字符串)。奇怪的是,(很长的字符串)在“规范授权值”错误指的是......

然后我尝试先用一个简单的方法解压 planet.osm.gz2

bzcat planet.osm.gz2 > planet.osm

并直接在 planet.osm 上运行解析器。而且……它奏效了!我对此感到非常困惑,并且找不到任何指示来说明为什么会发生这种情况以及如何解决这个问题。我的猜测是在解压缩和解析之间发生了一些事情,但我不确定。请帮助我理解!

最佳答案

原来问题出在压缩的planet.osm文件上。

OSM Wiki 所示,行星文件被压缩为多流文件,bz2 python模块无法读取多流文件。然而,bz2 文档指出了一个可以读取此类文件的替代模块,bz2file .我用过它,效果很好!

所以代码应该是:

from lxml import etree as et
from bz2file import BZ2File

path = "where/my/fileis.osm.bz2"
with BZ2File(path) as xml_file:
    parser = et.iterparse(xml_file, events=('end',))
    for events, elem in parser:

        if elem.tag == "tag":
            continue
        if elem.tag == "node":
            (do something)


    ## Do some cleaning
    # Get rid of that element
    elem.clear()

    # Also eliminate now-empty references from the root node to node        
    while elem.getprevious() is not None:
        del elem.getparent()[0]

此外,在对使用 PBF 格式进行一些研究(如评论中所建议的那样)时,我偶然发现了 imposm.parser ,一个为 OSM 数据(pbf 或 xml 格式)实现通用解析器的 python 模块。您可能想看看这个!

关于python - 在 python 中使用 lxml iterparse 解析大型 .bz2 文件 (40 GB)。未压缩文件不会出现的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51401704/

相关文章:

python - 为什么在 pandas 数据框列中应用更改 dtype

python - 使用 python 在文本中查找表情符号

c# - 如何不根据属性值序列化对象?

android - XML中没有更多建议

python - 相同的 xpath 在 Centos、Ubuntu 上返回不同的值

python - 使用黎曼和进行数值积分 (Python)

Python Neupy 安装 : no lapack/blas resources found

java - Android我自己的XML资源对象类型

python - 在搁置中保存 lxml 元素时出现类型错误

python - 使用命名空间解析 XML 时出现问题