Skip to main content
 首页 » 编程设计

python之如何使用 python/BeautifulSoup 或类似工具将 kml 文件解析为 csv

2025年05月04日11duanxz

我一直在尝试将 Google Earth KML 文件转换为 GIS shapefile(或其他 GIS 文件格式,例如 Postgresql/PostGIS 表)(请参阅 - GIS.stackexchange question here 基本上我想将 KML 文件转换为 CSV .

我的问题是 KML 文件包含一些存储在 HTML 表中的数据,因此解析后的 KML 文件在我生成的数据表中有一个字段包含 HTML,如下所示:

    "<br><br><br> 
<table border="1" padding="0"> 
<tr><td>ID_INT</td><td>NGA0104001</td></tr> 
<tr><td>N_sd</td><td>Igbere</td></tr> 
<tr><td>Skm2</td><td>3.34</td></tr> 
<tr><td>PT2010</td><td>13000</td></tr>" 

当使用 GDAL 库时,我最终得到一个 CSV 文件,其中一个字段包含一大块 HTML。我希望使用 BeautifulSoup(或一些类似的 Python 库)将 KML 文件的 HTML 元素解析为我的 CSV 文件中的四个独立字段。我似乎能够将 KML 传递给 BeautifulSoup,但我不确定从这里可以做什么,或者是否确实有另一种方法可以实现同样的事情。

我在这里和其他地方读过很多关于这个主题的类似问题,但真的不知道从哪里开始解析这个文件。有没有人成功实现这一目标?非常非常感谢...

哦,下面是我的 KML 文件中的一段代码作为示例:

 <?xml version="1.0" encoding="UTF-8"?> 
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"> 
    <Document> 
    <name>AFNGA_SWAC.kml</name> 
    <open>1</open> 
    <Style id="s_ylw-pushpin1"> 
        <IconStyle> 
            <scale>1.1</scale> 
            <Icon> 
                <href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href> 
            </Icon> 
            <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/> 
        </IconStyle> 
        <LineStyle> 
            <color>ff00ffff</color> 
            <width>3</width> 
        </LineStyle> 
        <PolyStyle> 
            <color>3300ffff</color> 
        </PolyStyle> 
    </Style> 
    <StyleMap id="m_ylw-pushpin1"> 
        <Pair> 
            <key>normal</key> 
            <styleUrl>#s_ylw-pushpin1</styleUrl> 
        </Pair> 
        <Pair> 
            <key>highlight</key> 
            <styleUrl>#s_ylw-pushpin_hl1</styleUrl> 
        </Pair> 
    </StyleMap> 
    <Style id="s_ylw-pushpin_hl1"> 
        <IconStyle> 
            <scale>1.3</scale> 
            <Icon> 
                <href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href> 
            </Icon> 
            <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/> 
        </IconStyle> 
        <LineStyle> 
            <color>ff00ffff</color> 
            <width>3</width> 
        </LineStyle> 
        <PolyStyle> 
            <color>3300ffff</color> 
        </PolyStyle> 
    </Style> 
    <Folder> 
        <name>AFNGA_SWAC</name> 
        <open>1</open> 
        <description>1027 Éléments de la couche Afnga_swac</description> 
        <Placemark> 
            <name>Aba</name> 
            <description><![CDATA[<br><br><br> 
    <table border="1" padding="0"> 
    <tr><td>ID_INT</td><td>NGA0101001</td></tr> 
    <tr><td>N_sd</td><td>Aba</td></tr> 
    <tr><td>Skm2</td><td>384.07</td></tr> 
    <tr><td>PT2010</td><td>1010000</td></tr>]]></description> 
            <styleUrl>#m_ylw-pushpin1</styleUrl> 
            <Polygon> 
                <extrude>1</extrude> 
                <tessellate>1</tessellate> 
                <outerBoundaryIs> 
                    <LinearRing> 
                        <coordinates> 
                            7.294567000000001,5.00267,0 7.294408999999999,5.002552,0 7.294211,5.002394,0 

请您参考如下方法:

Beautiful Soup 通常非常擅长直接找到您想要的内容(假设您可以轻松地在 xml/html 中识别一个包含您正在寻找的数据的模式)。我不知道您希望如何格式化输出,但是如果您要在 <description> 中查找数据标签,这实际上很简单(下面的示例来自 Python3):

from bs4 import BeautifulSoup 
 
inputfile = "whateveryourfileiscalled.xml" 
with open(inputfile, 'r') as f: 
  soup = BeautifulSoup(f) 
 
  # After you have a soup object, you can access tags very easily. 
  # For instance, you can iterate over and get <description> like so: 
 
  for node in soup.select('description'): 
       print(node) 

通常这不是很有用,所以深入一点,我们甚至可以访问我们在 <description> 中找到的节点内的元素。 .此外,如果需要,我们可以只隔离文本(使用“字符串”属性):

  for node in soup.select('description'): 
     for item in node.select('td'): 
         print(item.string) 

我总是打印以测试我是否得到了我想要的。如果那里什么都没有,你会得到很多 None秒。无论如何,这应该让你接近,显然,你可以用它做任何你想做的事情(存储在某个容器中,写出到 csv 等),而不是打印输出。这可能适用于您粘贴到评论中的 block ,但可能不适用于您最初问题中的 block ,因为您有多个描述标签。


在你的问题中,你有多个<description> tag 而不是所有这些都有节点,在这种情况下,您需要使用 find_all 而不是 select:

  for node in soup.find_all('description'): 
      for item in node.find_all('td'): 
          print(item.string)