You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python解析XML提取azimuthalGap并绘制直方图:代码返回空列表的优化求助

Python解析XML提取azimuthalGap并绘制直方图:代码返回空列表的优化求助

我有一份XML格式的ISC地震数据文件(示例片段见下文),写了一段Python脚本想要从中提取azimuthalGap的值,存入列表后绘制直方图,但目前运行代码后得到的gaps始终是空列表,希望能找到问题并优化代码。

我的代码目标是:

  • a. 遍历XML文件,找到<event> -> <origin> -> <quality>下的<azimuthalGap>节点
  • b. 将每个azimuthalGap的值存入gaps=[]变量
  • c. 基于这些值绘制直方图

目前尝试的代码如下:

import xml.etree.ElementTree as ET

def parse_azimuthal_gaps(xml_file):
    gaps = []

    # Parse the XML file
    tree = ET.parse(xml_file)
    root = tree.getroot()

    # Iterate through each event
    for event in root.findall(".//event"):
        origin = event.find(".//origin")
        if origin is not None:
            # Find the azimuthal gap (if present)
            azimuthal_gap = origin.find(".//quality/azimuthalGap")
            if azimuthal_gap is not None:
                gap_value = azimuthal_gap.text
                if gap_value is not None:
                    try:
                        gaps.append(float(gap_value))
                    except ValueError:
                        continue  # Skip if not a valid float

    return gaps

# Parse azimuthal gaps from the ISC XML file
gaps = parse_azimuthal_gaps("SCB_earthquakes.xml")
print("Azimuthal Gaps:", gaps[:10])  # Print the first 10 gaps for inspection

我的XML文件片段格式如下:

</event>
<event publicID="smi:ISC/evid=602401243">
  <preferredOriginID>smi:ISC/origid=601808754</preferredOriginID>
  <description>
    <text>Peru-Bolivia border region</text>
    <type>Flinn-Engdahl region</type>
  </description>
  <type>earthquake</type>
  <typeCertainty>known</typeCertainty>
  <comment>
    <text>Event reviewed by the ISC</text>
  </comment>
  <creationInfo>
    <agencyID>ISC</agencyID>
    <author>ISC</author>
  </creationInfo>
  <origin publicID="smi:ISC/origid=601808754">
    <time>
      <value>2011-01-23T09:13:37.30Z</value>
      <uncertainty>0.96</uncertainty>
    </time>
    <latitude>
      <value>-11.9240</value>
    </latitude>
    <longitude>
      <value>-68.9133</value>
    </longitude>
    <depth>
      <value>58000.0</value>
    </depth>
    <depthType>operator assigned</depthType>
    <quality>
      <usedPhaseCount>8</usedPhaseCount>
      <associatedStationCount>6</associatedStationCount>
      <standardError>0.4800</standardError>
      <azimuthalGap>353.000</azimuthalGap>
      <minimumDistance>4.260</minimumDistance>
      <maximumDistance>5.070</maximumDistance>
    </quality>
    <creationInfo>
      <author>SCB</author>
      <agencyID>SCB</agencyID>
    </creationInfo>
    <originUncertainty>
      <preferredDescription>uncertainty ellipse</preferredDescription>
      <minHorizontalUncertainty>20399.9996185303</minHorizontalUncertainty>
      <maxHorizontalUncertainty>96000</maxHorizontalUncertainty>
      <azimuthMaxHorizontalUncertainty>83.0</azimuthMaxHorizontalUncertainty>
    </originUncertainty>
    <arrival publicID="smi:ISC/pickid=637614753/hypid=601808754">
      <pickID>smi:ISC/pickid=637614753</pickID>
      <phase>Pn</phase>
      <azimuth>170.165</azimuth>
      <distance>4.404</distance>
      <timeResidual>3.6</timeResidual>
    </arrival>
    <arrival publicID="smi:ISC/pickid=637614754/hypid=601808754">
      <pickID>smi:ISC/pickid=637614754</pickID>
      <phase>Sn</phase>
      <azimuth>170.165</azimuth>
      <distance>4.404</distance>
      <timeResidual>4.6</timeResidual>
    </arrival>
  </origin>
  <pick publicID="smi:ISC/pickid=637614753">
    <time>
      <value>2011-01-23T09:14:46.10Z</value>
    </time>
    <waveformID networkCode="IR" stationCode="LPAZ"></waveformID>
    <onset>impulsive</onset>
    <polarity>positive</polarity>
    <phaseHint>Pn</phaseHint>
  </pick>
  <pick publicID="smi:ISC/pickid=637614754">
    <time>
      <value>2011-01-23T09:15:37.60Z</value>
    </time>
    <waveformID networkCode="IR" stationCode="LPAZ"></waveformID>
    <onset>emergent</onset>
    <phaseHint>Sn</phaseHint>
  </pick>
  <magnitude publicID="smi:ISC/magid=602398394">
    <mag>
      <value>3.80</value>
      <uncertainty>0.40</uncertainty>
    </mag>
    <type>Ml</type>
    <originID>smi:ISC/origid=601808754</originID>
    <stationCount>2</stationCount>
    <creationInfo>
      <author>SCB</author>
    </creationInfo>
  </magnitude>
  <preferredMagnitudeID>smi:ISC/magid=602398394</preferredMagnitudeID>

请问有没有办法优化这段代码,让它能正确提取到azimuthalGap的值?


问题排查与优化方案

看你的情况,大概率是XML命名空间在搞鬼——ISC的地震XML文件几乎都会带有命名空间声明(比如http://quakeml.org/xmlns/bed/1.2这类),而xml.etree.ElementTree默认不会处理命名空间,导致你的find/findall找不到对应节点。另外,递归查找//虽然能用,但精准定位层级会更可靠,也能避免误匹配深层节点。

优化后的完整代码(含命名空间处理+直方图绘制)

import xml.etree.ElementTree as ET
import matplotlib.pyplot as plt

def parse_azimuthal_gaps(xml_file):
    gaps = []
    tree = ET.parse(xml_file)
    root = tree.getroot()

    # 自动提取XML命名空间(如果存在)
    namespace = ""
    if '}' in root.tag:
        # 从根节点标签中拆分出命名空间
        namespace = root.tag.split('}')[0] + '}'
        # 如果自动提取有问题,也可以手动指定,比如:
        # namespace = "{http://quakeml.org/xmlns/bed/1.2}"

    # 精准层级查找:event -> origin -> quality -> azimuthalGap
    for event in root.findall(f".//{namespace}event"):
        # 找当前event下的直接origin子节点
        origin = event.find(f"{namespace}origin")
        if origin is not None:
            # 找当前origin下的直接quality子节点
            quality = origin.find(f"{namespace}quality")
            if quality is not None:
                azimuthal_gap = quality.find(f"{namespace}azimuthalGap")
                if azimuthal_gap is not None and azimuthal_gap.text is not None:
                    try:
                        # 去除文本前后空白后转成浮点数
                        gaps.append(float(azimuthal_gap.text.strip()))
                    except ValueError:
                        print(f"跳过无效的azimuthalGap值:{azimuthal_gap.text}")
                        continue
    return gaps

# 提取数据
gaps = parse_azimuthal_gaps("SCB_earthquakes.xml")

# 处理结果并绘图
if gaps:
    print(f"共提取到{len(gaps)}个azimuthalGap值,前10个为:{gaps[:10]}")
    # 绘制直方图
    plt.figure(figsize=(10,6))
    plt.hist(gaps, bins=20, edgecolor='black', alpha=0.7)
    plt.title('Azimuthal Gap 分布直方图')
    plt.xlabel('Azimuthal Gap 值')
    plt.ylabel('数据数量')
    plt.grid(axis='y', linestyle='--', alpha=0.7)
    plt.show()
else:
    print("未提取到任何azimuthalGap值,请检查:")
    print("1. XML文件路径是否正确")
    print("2. XML节点结构是否与预期一致")
    print("3. 命名空间是否需要手动指定")

关键优化说明:

  1. 命名空间自动适配:代码会自动识别XML的命名空间,不用手动硬编码,适配大多数ISC地震XML文件。
  2. 精准节点定位:把递归查找改成直接子节点查找,减少无效遍历,避免匹配到错误层级的节点。
  3. 增加异常提示:遇到非数值的无效值时会打印提示,方便你排查数据问题。
  4. 整合绘图逻辑:直接把直方图绘制功能加了进去,提取到数据后自动生成可视化图表。

另外,记得确认SCB_earthquakes.xml和脚本在同一目录下,或者使用绝对路径指定文件位置哦。

备注:内容来源于stack exchange,提问作者tonino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:23:08